Socket

소켓통신으로 실시간 메모장 데이터 보내기 (python)

섭섭입니다 2020. 7. 29. 17:27

우선, 이번 학교에서 있는 캡스톤 대회 준비하는데 필요한 소켓통신 부분을 python 으로 시도해 보았다.

 

 

먼저 메모장의 데이터를 python 으로 소켓통신 하기 전에

 

간단한 메시지를 주고 받는 예제를 이용하여 조금 각색해 보았다.

 

 

[ 서버 -- 라즈베리파이 /  클라이언트 -- PC ]

 

 

다음은 간단한 예제 코드이다.

 

< Server.py >

import socket

# 접속할 서버 주소입니다. 여기에서는 루프백(loopback) 인터페이스 주소 즉 localhost를 사용합니다. 
HOST = '127.0.0.1'

# 클라이언트 접속을 대기하는 포트 번호입니다.   
PORT = 9999        

# 소켓 객체를 생성합니다. 
# 주소 체계(address family)로 IPv4, 소켓 타입으로 TCP 사용합니다.  
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


# 포트 사용중이라 연결할 수 없다는 
# WinError 10048 에러 해결를 위해 필요합니다. 
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)


# bind 함수는 소켓을 특정 네트워크 인터페이스와 포트 번호에 연결하는데 사용됩니다.
# HOST는 hostname, ip address, 빈 문자열 ""이 될 수 있습니다.
# 빈 문자열이면 모든 네트워크 인터페이스로부터의 접속을 허용합니다. 
# PORT는 1-65535 사이의 숫자를 사용할 수 있습니다.  
server_socket.bind((HOST, PORT))

# 서버가 클라이언트의 접속을 허용하도록 합니다. 
server_socket.listen()

# accept 함수에서 대기하다가 클라이언트가 접속하면 새로운 소켓을 리턴합니다. 
client_socket, addr = server_socket.accept()

# 접속한 클라이언트의 주소입니다.
print('Connected by', addr)


# 무한루프를 돌면서 
while True:

    # 클라이언트가 보낸 메시지를 수신하기 위해 대기합니다. 
    data = client_socket.recv(1024)

    # 빈 문자열을 수신하면 루프를 중지합니다. 
    if not data:
        break


    # 수신받은 문자열을 출력합니다.
    print('Received from', addr, data.decode())

    # 받은 문자열을 다시 클라이언트로 전송해줍니다.(에코) 
    client_socket.sendall(data)


# 소켓을 닫습니다.
client_socket.close()
server_socket.close()

 

 

 

< Client.py >

import socket


# 서버의 주소입니다. hostname 또는 ip address를 사용할 수 있습니다.
HOST = '127.0.0.1'  
# 서버에서 지정해 놓은 포트 번호입니다. 
PORT = 9999       


# 소켓 객체를 생성합니다. 
# 주소 체계(address family)로 IPv4, 소켓 타입으로 TCP 사용합니다.  
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


# 지정한 HOST와 PORT를 사용하여 서버에 접속합니다. 
client_socket.connect((HOST, PORT))

# 메시지를 전송합니다. 
client_socket.sendall('안녕'.encode())

# 메시지를 수신합니다. 
data = client_socket.recv(1024)
print('Received', repr(data.decode()))

# 소켓을 닫습니다.
client_socket.close()

 

 

위의 코드를 조금 각색하여 내가 준비하는 것에 어울리는 코드로 만들어 보았다.

 

 

 

서버에서 메모장의 내용을 읽어 클라이언트로 보내주는데

 

여기서 중요한 건 메모장의 내용을 실시간으로 읽는다는 것이다.

 

 

 

실시간으로 메모장을 읽어 내용이 바뀌게 되면 바뀐 내용의 것으로 바꾸어 보내주어 클라이언트의 메모장에 정확히 바뀌게 된다.

 

 

우선 서버 코드이다.  [ 메모장의 데이터를 읽고 보내주는 소켓 통신 코드 ]

 

< Server.py >

 

import socket


# 접속할 서버 주소입니다. 여기에서는 루프백(loopback) 인터페이스 주소 즉 localhost를 사용합니다. 
HOST = '127.0.0.1'

# 클라이언트 접속을 대기하는 포트 번호입니다.   
PORT = 9999        



# 소켓 객체를 생성합니다. 
# 주소 체계(address family)로 IPv4, 소켓 타입으로 TCP 사용합니다.  
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


# 포트 사용중이라 연결할 수 없다는 
# WinError 10048 에러 해결를 위해 필요합니다. 
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)


# bind 함수는 소켓을 특정 네트워크 인터페이스와 포트 번호에 연결하는데 사용됩니다.
# HOST는 hostname, ip address, 빈 문자열 ""이 될 수 있습니다.
# 빈 문자열이면 모든 네트워크 인터페이스로부터의 접속을 허용합니다. 
# PORT는 1-65535 사이의 숫자를 사용할 수 있습니다.  
server_socket.bind((HOST, PORT))

# 서버가 클라이언트의 접속을 허용하도록 합니다. 
server_socket.listen()

# accept 함수에서 대기하다가 클라이언트가 접속하면 새로운 소켓을 리턴합니다. 
client_socket, addr = server_socket.accept()

# 접속한 클라이언트의 주소입니다.
print('Connected by', addr)

copy ='0'

# 무한루프를 돌면서 
while True:
     
    f = open('hello.txt', 'r')
    s = f.read()
    f.close()
   
    if copy == s:
        continue
    else:
        print('메모장의 내용',s)
         # 메모장의 내용을 클라이언트로 전송    
        copy = s
        client_socket.sendall(s.encode())


    
# 소켓을 닫습니다.
client_socket.close()
server_socket.close()

 

 

여기서 while 문이 중요하다. copy 라는 변수를 while 문 이전에 설정해주고, 반복을 실시 할 것인데 우선 hello.txt 라는 메모장의 을 열어 읽을 것이다. 그것을 s라는 변수에 저장하고 미리 설정해 준 copy 라는 것과 같다면 continue 되어 아랫줄은 실행되지 않고 계속 실시간으로 읽어오는 것만 반복 될 것이다. 하지만 같지 않다면 (새로운 것이 메모장에 적힌다면) 그 내용을 프린트하며 copy 입력된 s의 값을 넣어주고 client로 보내준다. 여기서 s를 넣어주는 이유는 다시 반복될 때 if의 조건대로 같아야 한 번만 print하고 send 할 것이기 때문이다 

 

 

다음은 Client 코드이다. 

 

< Client.py >

 

import socket


# 서버의 주소입니다. hostname 또는 ip address를 사용할 수 있습니다.
HOST = '127.0.0.1'  
# 서버에서 지정해 놓은 포트 번호입니다. 
PORT = 9999       


# 소켓 객체를 생성합니다. 
# 주소 체계(address family)로 IPv4, 소켓 타입으로 TCP 사용합니다.  
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


# 지정한 HOST와 PORT를 사용하여 서버에 접속합니다. 
client_socket.connect((HOST, PORT))

# 메시지를 전송합니다. 


# 메시지를 수신합니다.

copy ='0'

while True:

    data = client_socket.recv(1024)

    if copy == data:
        continue
    else:
        print('서버로 부터 받은 메모장의 내용', repr(data.decode()))
        
        copy = data

        f = open('helloClient.txt', 'w')
        f.write(data.decode())
        f.close()
    

# 소켓을 닫습니다.
client_socket.close()

 

여기도 마찬가지로 while 문을 이용해서 반복을 수행하였다. 

 

조건은 위 서버의 설명과 비슷하다. 

 

 

 

위와 같은 코드를 실행 결과이다. 

 

영상 왼쪽이 서버 , 오른쪽이 클라이언트 이다.

 

 

 

위와 같이 메모장을 실시간으로 읽어 클라이언트로 보내는 것이 가능하다.

 

 

라즈베리파이에 적용시켜 라즈베리파이와 PC의 소켓통신도 가능하다.

 

 

참고 블로그 : webnautes.tistory.com/1381