# Python 网络套接字编程教程

> 原文： [https://pythonspot.com/python-network-sockets-programming-tutorial/](https://pythonspot.com/python-network-sockets-programming-tutorial/)

在本教程中，您将学习[**网络编程**](https://pythonspot.com/en/network/)。您将了解用于万维网，电子邮件和许多其他应用程序的客户端-服务器模型。

![client server](img/7ebef81ff83b49c4f531247f8fb26cc7.jpg)

客户端服务器（带有电子邮件协议）客户端服务器模型是一个模型，其中有 n 个客户端和一个服务器。 客户端向服务器发出数据请求。 服务器回复收到的那些消息。 客户端可以是任何设备，例如您的计算机或平板电脑。 服务器通常是要 24/7 连接的专用计算机。

### 套接字服务器代码

此代码将使用套接字启动一个简单的 Web 服务器。 它等待连接，如果接收到连接，它将输出接收到的字节。

```py
#!/usr/bin/env python

import socket

TCP_IP = '127.0.0.1'
TCP_PORT = 62
BUFFER_SIZE = 20  # Normally 1024, but we want fast response

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)

conn, addr = s.accept()
print 'Connection address:', addr
while 1:
     data = conn.recv(BUFFER_SIZE)
     if not data: break
     print "received data:", data
     conn.send(data)  # echo
conn.close()

```

Execute with:

```py
$ python server.py

```

将在端口 62 处打开 Web 服务器。 在第二个屏幕中，使用 Telnet 打开客户端。 如果将同一台计算机用于客户端和服务器，请使用：

```py
$ telnet 127.0.0.1 62.

```

如果将另一台计算机用作客户端，请键入该计算机的相应 IP 地址。您可以使用`ifconfig`找到它。

您从客户端编写的所有内容都将到达服务器。 服务器将收到的消息发回。下面是一个示例输出（单击放大）

### 套接字网络客户端：

下面的客户端脚本将消息发送到服务器。 服务器必须正在运行！

```py
#!/usr/bin/env python

import socket

TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 1024
MESSAGE = "Hello, World!"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()

print "received data:", data

```

该客户端仅模仿我们在 Telnet 中所做的行为。

## 服务器代码的限制

上面的服务器代码只能与一个客户端交互。 如果您尝试连接第二个终端，则根本不会回复新客户端。 要使服务器与多个客户端交互，您需要使用多线程。 我们重建服务器脚本以接受多个客户端连接：

```py
#!/usr/bin/env python

import socket
from threading import Thread
from SocketServer import ThreadingMixIn

class ClientThread(Thread):

    def __init__(self,ip,port):
        Thread.__init__(self)
        self.ip = ip
        self.port = port
        print "[+] New thread started for "+ip+":"+str(port)

    def run(self):
        while True:
            data = conn.recv(2048)
            if not data: break
            print "received data:", data
            conn.send(data)  # echo

TCP_IP = '0.0.0.0'
TCP_PORT = 62
BUFFER_SIZE = 20  # Normally 1024, but we want fast response

tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((TCP_IP, TCP_PORT))
threads = []

while True:
    tcpsock.listen(4)
    print "Waiting for incoming connections..."
    (conn, (ip,port)) = tcpsock.accept()
    newthread = ClientThread(ip,port)
    newthread.start()
    threads.append(newthread)

for t in threads:
    t.join()

```

### 应用协议

到目前为止，我们只是来回发送了消息。每个消息在应用程序中可以具有特定的含义。这就是所谓的协议。这些消息的含义在发送方和接收方都必须相同。下面的传输层确保接收到消息（TCP）。网络层是 IPv4 协议。我们需要定义的只是应用层。

下面我们修改了服务器以接受简单命令（为简单起见，我们使用非线程服务器）。我们将端口更改为 64。带有协议的服务器代码：

```py
#!/usr/bin/env python

import socket

TCP_IP = '127.0.0.1'
TCP_PORT = 64
BUFFER_SIZE = 20  # Normally 1024, but we want fast response

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)

conn, addr = s.accept()
print 'Connection address:', addr
while 1:
     data = conn.recv(BUFFER_SIZE)
     if not data: break
     print "received data:", data
     #conn.send(data)  # echo
     if "/version" in data:
         conn.send("Demo versionn")

     if "/echo" in data:
         data = data.replace("/echo","")
         conn.send(data + "n")

conn.close()

```

使用以下命令运行服务器：

```py
sudo python server.py

```

然后，客户端可以与 telnet 连接（确保选择正确的 IP）：

```py
$ telnet 127.0.0.1 64
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
message
/version
Demo version
/echo Repeat this
 Repeat this

```

[下载套接字代码](https://pythonspot.com/en/download-code/?id=L3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDE2LzA4L3NvY2tldHNUdXRvcmlhbC56aXA=)