본문 바로가기
Python

파이썬 소켓 프로그래밍(1)

by 웹하는빡통 2019. 11. 12.

간단한 메시지 송/수신 프로그램 구현. 

 

client socket code

 

클라이언트 소켓 세팅 

 

clientSock = socket(AF_INET, SOCK_STREAM)
clientSock.connect(('IP 주소', 8980))
bind와 listen, accept 과정이 빠지고 대신 connect가 추가된다. 클라이언트에서 서버에 접속하기 위해선 connect()만 실행해주면 된다. 여기에도 어드레스 패밀리가 인자로 들어가고, 호스트 주소와 포트번호로 구성된 튜플이 요구되는데.

IP주소는 자기 자신을 의미하므로, 위의 AF는 자기 자신에게 8980번 포트로 연결하라는 의미다.

 


소켓 송수신

서버 소켓 세팅에서는 connectionSock을 이용해서 데이터를 주고 받는다. 클라이언트는 어차피 사용하는 소켓이 clientSock이므로 헷갈릴 일이 없겠지만, 서버는 두 개의 소켓이 있으므로 이를 유의해야 한다. bind()로 서버를 구성한 소켓으로는 데이터를 주고 받지 않는다.

그렇다면 소켓으로 어떻게 데이터를 주고 받을 수 있을까? 메소드 이름이 아주 간단하다. 
send()와 recv()를 이용하면 된다. send()는 보내는 메소드/recv()는 받는 메소드.

 

clientsock.send(Hello I AM Client'.encode('utf-8'))

여기서 문자열을 전송할 때 encode()을 이용한다. 파이썬 문자열의 encode() 메소드는 문자열을 byte로 변환해주는 메소드이기 때문이다. 파이썬 내부에서 다뤄지는 문자열은 파이썬에서 생성된 객체이고, 이를 바로 트랜스포트에 그대로 싣는 것은 불가능합니다. 그러므로 적절한 인코딩을 하여 보내야만 합니다. 만약 encode()을 사용하지 않을 경우 에러가 발생 한다. 

이제 상대방에게서 온 메시지를 확인해 보겠다.


data =clientsock.recv(1024)
print(''.decode('utf-8'))

recv()를 실행하면 소켓에 메시지가 실제로 수신될 때까지 파이썬 코드는 대기하게 된다. 마치 accept() 처럼 . 인자로는 수신할 바이트의 크기를 지정할 수 있습니다. recv(1024)는 소켓에서 1024byte 만큼 가져온다. 

아까 send()를 실행할 때는 문자열을 인코딩해서 보냈는데, recv()를 할 때는 데이터를 바이트로 수신하므로, 문자열로서 활용하기 위해선 디코딩을 해야한다. 이 또한 decode()를 이용하여 적절하게 문자열로 디코딩할 수 있다.


 

Server socket code

서버 소켓 세팅

1. socket 객체 생성 후 인자로 두 가지를 넣어주는데 
AF(Address Family)와 소켓 타입이다.

소켓 타입에는 3종류가 있는데 row,stream,데이터그램이다.
보통은 stream을 많이 사용한다.

AF는 주소 체계에 해당하는데 
1. AF_INET(ipv4를 의미)
2. AF_INET6(ipv6를 의미)

2. 생성한 소켓을 bind를 해주어야한다. 
이는 클라이언트를 만들 때는 불필요하나, 서버를 운용할 때에는 반드시 필요하다.
serversock.bind(('', 8080)): 생성된 소켓의 번호와 실제 AF를 연결해준다.
또한 앞부분 공백은 IP, 뒷 부분은 포트를 정의해준다. 

인터페이스와 연결하고 싶다면 빈 문자열을 넣으면 되고. 반대로 브로드캐스트를 하고 싶다면 ''를 입력하면 된다. 

즉, 위의 bind는 8080번 포트에서 모든 인터페이스에게 연결하도록 한다라고 생각하면 되겠다.


3. serversock.listen(1)은 bind와 마찬가지로 서버에만 필요로 한다.
listen 안에 1의 의미는 소켓이 총 몇개의 동시접속을 허용할 것이냐라는 의미이다.
즉 1을 넣으면 단 하나의 접속만 허용한다는 것이다. 

4. connectionSock, addr = serversock.accept():여기서 accept()은 소켓에 누군가가 접속하여 연결되었을 때에 비로소 결과값이 return되는 함수이다. 즉, 소스코드 내에 serversock.accept()이 있더라도, 누군가가 접속할 때까지 프로그램은 바로 이 부분에서 계속 멈춰있게 된다. 상대방이 접속함으로써 accept()가 실행되면, return 값으로 새로운 소켓과, 상대방의 AF를 전달해주게 된다. 

 

 

결과

 

실행 순서는 서버를 먼저 실행하고 그 다음 클라이언트를 실행 하면 된다.

댓글