오늘날 인터넷에서 소켓 프로토콜은 가장 중요한 기반 중 하나입니다. 이 문서에서는 Python에서 소켓 프로그래밍 작업의 모든 영역을 다룹니다.
소켓은 오늘날의 네트워크를 구성하는 다양한 통신 프로토콜입니다. 이러한 프로토콜을 사용하면 서로 다른 두 프로그램이나 장치 간에 정보를 전송할 수 있습니다. 예를 들어, 브라우저를 열면 클라이언트로서 정보를 전송하기 위해 서버에 대한 연결을 만듭니다.
이 통신 원리를 살펴보기 전에 먼저 소켓이 무엇인지 명확히 하겠습니다.
일반적으로 소켓은 데이터 전송 및 수신을 위해 만들어진 내부 애플리케이션 프로토콜입니다. 단일 네트워크에는 두 개의 소켓이 있으며 각 통신 장치 또는 프로그램마다 하나씩 있으며 이러한 소켓은 IP 주소와 포트의 조합입니다. 사용된 포트 번호에 따라 단일 장치는 "n"개의 소켓을 가질 수 있으며, 다양한 유형의 프로토콜에 대해 서로 다른 포트를 사용할 수 있습니다.
아래 그림은 몇 가지 일반적인 포트 번호와 관련 프로토콜 정보를 보여줍니다.
Protocol |
포트 번호 |
Python 라이브러리 |
앱 |
HTTP |
80 |
httplib, urllib, 요청 |
웹, 웹사이트 |
FTP |
20 |
ftplib |
파일 전송 |
NNTP |
119 |
nttplib |
뉴스 전송 |
SMTP |
25 |
smtplib |
메일 보내기 |
Telnet |
23 |
telnetlib |
명령줄 |
POP3 |
110 |
poplib |
메일 받기 |
Gopher |
70 |
gopherlib |
문서 전송 |
이제 소켓의 개념을 이해했으니 Python의 소켓 모듈을 살펴보겠습니다.
Python에서 소켓 프로그래밍을 구현하려면 소켓 모듈을 가져와야 합니다.
이 모듈의 몇 가지 중요한 메소드는 다음과 같습니다:
Method |
Description |
socket.socket() |
은(는) 다음을 만드는 데 사용됩니다. 소켓 (서버 클라이언트와 클라이언트가 모두 생성되어야 함) |
socket.accept() |
은 연결을 수락하는 데 사용됩니다. 한 쌍의 값(conn, address)을 반환합니다. 여기서 conn은 데이터를 보내거나 받는 데 사용되는 새 소켓 개체이고 address는 연결의 다른 쪽 끝에 있는 소켓 주소입니다. |
socket.bind () |
매개변수로 지정된 주소에 바인딩하는 데 사용됩니다. 연결( ) |
socket.listen() |
|
이제 소켓 모듈의 중요성을 이해했으므로 Python에서 서버와 클라이언트를 구축하는 방법을 살펴보겠습니다. 서버란 무엇입니까서버는 네트워크 리소스를 관리하는 데 특별히 사용되는 프로그램, 컴퓨터 또는 장치입니다. 서버는 동일한 장치나 컴퓨터에 있을 수도 있고, 다른 장치나 컴퓨터에 로컬로 연결될 수도 있고, 원격으로 연결될 수도 있습니다. 데이터베이스 서버, 웹 서버, 인쇄 서버 등 다양한 유형의 서버가 있습니다. 서버는 일반적으로 소켓.socket(), 소켓.bind(), 소켓.listen() 등을 사용하여 연결을 설정하고 클라이언트에 바인딩합니다. 이제 서버를 생성하는 프로그램을 작성해 보겠습니다. import socket s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((socket.gethostname(),1234)) #port number can be anything between 0-65535(we usually specify non-previleged ports which are > 1023) s.listen(5) while True: clt,adr=s.accept() print(f"Connection to {adr}established") #f string is literal string prefixed with f which #contains python expressions inside braces clt.send(bytes("Socket Programming in Python","utf-8 ")) #to send info to clientsocket 소켓을 생성하기 위해 가장 먼저 필요한 조건은 해당 모듈을 import하는 것입니다. 그런 다음 소켓.socket() 메서드를 사용하여 서버측 소켓을 만듭니다. AF_INET은 인터넷의 주소를 나타내며 쌍(호스트, 포트)이 필요합니다. 여기서 호스트는 특정 웹 사이트의 URL 또는 해당 주소일 수 있으며 포트 번호는 정수입니다. SOCK_STREAM은 TCP 프로토콜을 생성하는 데 사용됩니다. bind() 메소드는 두 개의 매개변수를 튜플로(호스트, 포트) 받아들입니다. 여기서는 4자리 포트 번호를 사용하는 것이 가장 좋다는 점에 유의해야 합니다. 낮은 포트 번호는 일반적으로 시스템에서 사용하거나 예약하기 때문입니다. Listen() 메서드를 사용하면 서버가 연결을 수락할 수 있으며 5는 동시에 허용되는 여러 연결에 대한 대기열입니다. 여기서 지정할 수 있는 최소값은 0이며, 매개변수를 지정하지 않으면 기본적으로 적절한 매개변수가 사용됩니다. while 루프를 사용하면 연결을 영원히 허용할 수 있고, clt와 adr은 클라이언트 개체와 주소이고, print 문은 클라이언트 소켓의 주소와 포트 번호만 인쇄하며, 마지막으로 clt.send는 데이터를 바이트 단위로 보내는 데 사용됩니다. . 이제 서버가 설정되었으므로 클라이언트로 넘어가겠습니다. 클라이언트란 무엇입니까클라이언트는 서버로부터 정보나 서비스를 받는 컴퓨터 또는 소프트웨어입니다. 클라이언트-서버 모델에서는 클라이언트가 서버에 서비스를 요청합니다. 가장 좋은 예는 Google Chrome, Firefox 등과 같은 웹 브라우저입니다. 이러한 웹 브라우저는 사용자의 지시에 따라 필요한 웹 페이지와 서비스를 제공하도록 웹 서버에 요청합니다. 다른 예로는 온라인 게임, 온라인 채팅 등이 있습니다. 이제 Python 프로그래밍 언어로 클라이언트 프로그램을 작성하는 방법을 살펴보겠습니다. import socket s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((socket.gethostname(), 2346)) msg=s.recv(1024) print(msg.decode("utf-8")) 먼저 소켓 모듈을 가져온 다음 서버를 생성할 때 했던 것처럼 소켓을 생성합니다. 그런 다음 클라이언트와 서버 간의 연결을 생성하려면 (호스트, 포트)를 지정하여 connect() 메서드를 사용해야 합니다. 참고: 클라이언트와 서버가 동일한 컴퓨터에 있는 경우 gethostname을 사용해야 합니다. (LAN–localip/WAN–publicip) 여기서 클라이언트는 서버로부터 일부 정보를 수신하려고 합니다. 이를 위해 우리는 recv() 메소드를 사용해야 하며, 정보는 다른 변수 msg에 저장됩니다. 전송되는 정보는 바이트 단위이며 위 프로그램의 클라이언트에서는 한 번의 전송으로 최대 1024바이트(버퍼 크기)를 수신할 수 있다는 점에 유의하는 것이 중요합니다. 전송되는 정보의 양에 따라 임의의 숫자로 지정할 수 있습니다. 마지막으로 전송되는 메시지를 디코딩하고 인쇄합니다. 이제 클라이언트-서버 프로그램을 만드는 방법을 이해했으니 어떻게 실행해야 하는지 살펴보겠습니다. 클라이언트-서버 상호 작용 이 프로그램을 실행하려면 명령 프로그램을 열고 클라이언트 및 서버 프로그램이 생성된 폴더에 들어간 다음 다음을 입력해야 합니다. py server.py #这里,server.py 是服务器的文件名 예상대로 서버가 실행되기 시작합니다
클라이언트를 실행하려면 다른 cmd 창을 열고 다음을 입력해야 합니다. pyclient.py 버퍼 크기를 7로 줄이고 동일한 프로그램이 어떻게 보이는지 살펴보겠습니다. 그림에 표시된 대로, 7바이트 후에 전송하면 연결이 종료됩니다. 사실 아직 완전한 정보를 받지 못해서 문제인데, 연결이 일찍 끊어졌네요. 다중 통신 클라이언트가 완전한 메시지를 받을 때까지 연결을 계속하기 위해 while 루프를 사용할 수 있습니다. import socket s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((socket.gethostname(), 2346)) while True: msg=s.recv(7) print(msg.decode("utf-8")) 그러한 수정 후 각 전송은 7바이트의 완전한 메시지를 받게 됩니다. 하지만 이로 인해 또 다른 문제가 발생합니다. 연결이 절대 종료되지 않으며 언제 종료될지 알 수 없습니다. 또한, 클라이언트가 서버로부터 받게 될 메시지나 정보의 크기가 얼마나 큰지 실제로 알지 못한다면 어떻게 될까요? 이런 경우에는 계속해서 코드를 개선해야 합니다. complete_info='' while True: msg = s.recv(7) if len(msg)<=0: break complete_info += msg.decode("utf-8") print(complete_info) 서버측에서는 아래와 같이 close() 메소드를 사용합니다. clt.close() 출력은 다음과 같습니다. 程序会检查信息的大小,并将其打印到一次两个字节的缓冲区中,然后在完成连接后关闭连接。 传输 Python 对象目前为止我们仅仅掌握了传递字符串的方法,但是,Python 中的 Socket 编程也允许我们传输 Python 对象。这些对象可以是集合、元组、字典等。要实现这一点,需要用到 Python 的 pickle 模块。 Python pickle模块 当我们实际序列化或反序列化 Python 中的对象时,就会使用到 Python pickle 模块。让我们看一个小例子 import pickle mylist=[1,2,'abc'] mymsg = pickle.dumps(mylist) print(mymsg) Output: b’x80x03]qx00(Kx01Kx02Xx03x00x00x00abcqx01e.’ 在上面的程序中,mylist是使用pickle模块的dumps()函数序列化的。还要注意,输出以b开头,表示它已转换为字节。在 socket 编程中,可以实现此模块以在客户端和服务器之间传输 python 对象。 如何使用 pickle 模块传输 Python 对象 当我们将 pickle 与 socket 一起使用时,完全可以通过网络传输任何内容。 先来看看服务端代码 Server-Side: import socket import pickle a=10 s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((socket.gethostname(), 2133))#binding tuple s.listen(5) while True: clt , adr = s.accept() print(f"Connection to {adr}established") m={1:"Client", 2:"Server"} mymsg = pickle.dumps(m)#the msg we want to print later mymsg = {len(mymsg):{a}}"utf-8") + mymsg clt.send(mymsg) 这里,m是一个字典,它基本上是一个需要从服务器发送到客户端的 Python 对象。这是通过首先使用dumps()序列化对象,然后将其转换为字节来完成的。 现在,让我们记下客户端: Client-Side: import socket import pickle a=10 s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((socket.gethostname(), 2133)) while True: complete_info = b'' rec_msg = True while True: mymsg = s.recv(10) if rec_msg: print(f"The length of message = {mymsg[:a]}") x = int (mymsg[:a ] ) rec_msg = False complete_info += mymsg if len(complete_info)-a == x: print("Recieved the complete info") print(complete_info[a:]) m = pickle.loads(complete_info[a:]) print(m) rec_msg = True complete_info = b'' print(complete_info) 第一个while循环将帮助我们跟踪完整的消息(complete_info)以及正在使用缓冲区接收的消息(rec_msg)。 然后,在接收消息时,我们所做的就是打印每一位消息,并将其放在大小为10的缓冲区中接收。此大小可以是任何大小,具体取决于个人选择。 然后如果收到的消息等于完整消息,我们只会将消息打印为收到的完整信息,然后使用loads()反序列化消息。 输出如下: |
위 내용은 Python 소켓 프로그래밍에 대한 자세한 설명과 실무 가이드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!