티스토리 뷰

python

Python 소켓 모듈 사용

on1ystar 2019. 3. 17. 17:17
728x90
반응형

소켓 프로그래밍의 개념적인 부분 참조 : 네트워크 소켓 프로그래밍 개요

명령행 인자 부분 참조 : Python argparse 명령행 인자 받기

클라이언트가 보내준 문자열을 거꾸로 전송해주는 서버 구현


> python client.py -i '서버 ip주소' -p '포트 번호'

> python server.py -p '포트 번호' -s '문자열'


## client.py

import socket
import argparse

def run(host, port, strList):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, port))
msg = " ".join(strList) ## 리스트 요소 사이에 공백을 넣어 스트링으로 변환
s.sendall(msg.encode())

resp = s.recv(1024)
print(resp.decode())

if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Echo client -p port -i host -s string")
parser.add_argument('-p', help="port_number", required=True)
parser.add_argument('-i', help="host_name", required=True)
parser.add_argument('-s', help="input_string", nargs='+', required=True)

args = parser.parse_args()
run(host=args.i, port=int(args.p), strList=args.s)


## sever.py

import socket
import argparse

def run_server(port=4000):
host = '' ## 127.0.0.1 Loop back

with socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) as s:
s.bind((host, port))
s.listen(1) ## max 1 client

conn, addr = s.accept()
msg = conn.recv(1024)
rMsg = reverseMsg(msg.decode()) ## msg is a binary data, so we need to decode it
print(rMsg)

conn.sendall(rMsg.encode())
conn.close()

## 입력한 문자열을 반대로 뒤집어 주는 함수
def reverseMsg(str):
size = len(str)
reverseStr=''
for i in range(size-1, -1, -1):
reverseStr+=str[i]
return reverseStr

if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Echo server -p port")
parser.add_argument('-p', help="port_number", required=True)

args = parser.parse_args()
run_server(port=int(args.p))


socket.socket()

소켓 객체를 생성하는 함수

첫 번째 인자-family : 주소 체계를 지정하는 인자로 socket.AF_INET = IP4v, socket.AF_INET6 = IP6v에 많이 쓰임

두 번째 인자-type : 소켓의 타입으로 raw 소켓, 스트림 소켓, 데이터그램 소켓 등이 있다.


with as

파일이나 소켓을 with as 구문으로 생성하면 후에 소멸을 close() 메소드를 호출하지 않아도 인터프리터가 자동으로 해준다.


socket.bind()

클라이언트에서는 필요 없고 서버를 만들 때 필요한 메소드로 튜플 형식을 받게 되있다.

튜플의 앞 부분-ip address    :    "(공백)을 입력하면 루프 백 주소로 자기 자신을 의미한다.

튜플의 뒷 부분-port number


socket.connet()

클라이언트에서 서버에 접속하기 위해 AF가 인자로 들어가는데, (호스트 주소, 포트번호)로 구성된 튜플을 인자로 전달한다.


socket.listen()

서버가 데이터 수신을 기다리는 상태로 인자 값으로 들어가는 숫자는 해당 소켓이 몇 개의 동시접속을 허용할 것이냐는 의미이다.


socket.accept()

소켓에 누군가가 접속하여 연결되었을 때 결과 값이 튜플로 return 되는 함수다. return 값은 새로운 소켓과 상대방의 AF(Address Family)를 전달한다.

이 이후 부터의 데이터 송수신은 새로운 소켓을 이용한다.


socket.sendall(), socket.recv()

데이터를 송수신 하는 메소드다.

여기서 몇 가지 주의해야 할 점은 클라이언트는 기존의 소켓으로 송수신을 하는 반면, 서버는 accpet()로 생성된 소켓으로 송수신을 한다는 것이다.

그리고 문자열을 전송할 때 encode()를 수행해 줘야 하는데, 이 encode() 메소드는 문자열을 byte로 변환해주는 메소드다.

파이썬 내부에서 생성된 문자열은 파이썬에서 생성된 객체이므로 전송 계층에 문자열을 그대로 보내면 에러가 발생한다.

물론 이 문자열을 읽어 출력할 때는 decode()를 사용해야 한다.

마지막으로 소켓은 턴 바이 턴 형식이기 때문에 데이터를 한 번 송신하면 다음은 수신을 해야 한다. 

728x90
반응형

'python' 카테고리의 다른 글

Python 소켓으로 파일 보내기  (1) 2019.03.24
Python 파일 처리  (0) 2019.03.23
Python argparse 명령행 인자 받기  (0) 2019.03.17
Python List tip, lambda  (0) 2019.03.13
Python mutable vs immutable  (0) 2019.03.12
댓글