Python网络编程

  初学Python语言,今天搭建了Python环境,经朋友推荐,采用PyCharm+Anaconda搭建的环境,Anaconda是Python的开源发行版本,省去了包管理和不同Python版本的问题。由于之前熟悉网络编程,熟悉了Python基本语法后,实现了简单的网络编程。

  本篇文章包括三个部分,首先介绍了一下Socket网络编程的基础知识,然后分别从服务器端和客户端介绍了网络通信原理及代码实现。

1. Socket基础知识

Socket通信模型

  建立Socket连接至少需要一对套接字,其中一个运行客户端,另一个运行于服务器端。

  套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

  (1)服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

  (2)客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。(为此,客户端套接字必须首先描述它要连接的服务器的套接字,指出服务器套接字的地址和端口号,然后就向服务器套接字提出连接请求)

  (3)连接确认:当服务器套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。(而服务器套接字继续处于监听状态,继续接收其他客户端套接字的连接请求)

2. 服务器端

服务器端创建Socket并绑定监听的地址和端口,并调用listen()方法开始监听端口,传入的参数指定等待连接的最大数量。

# 服务器建立socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定监听的地址和端口
s.bind(('127.0.0.1', 9999))
# 开始监听端口
s.listen(5)
print('Waiting for connection...')

服务器端通过while死循环不断监听来自客户端的连接请求,一旦有客户端连接,服务器的accept()方法接收请求,并创建新的线程处理请求。

while True:
    # 接受一个新连接;
    sock, addr = s.accept()
    # 创建新线程来处理TCP连接:
    t = threading.Thread(target=tcplink, args=(sock,addr))
    t.start()

服务器端采用多线程实现,每连接到一个客户端就创建一个新的线程,避免服务器单线程带来的阻塞问题。

def tcplink(sock, addr):
    print('Accept new connection from %s:%s...' % addr)
    sock.send(b'Welcome!')
    while True:
        data = sock.recv(1024)
        time.sleep(1)
        if not data or data.decode('utf-8') == 'exit':
            break
        sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
    sock.close()
    print('Connection from %s:%s closed' % addr)

连接建立后,客户端和服务器便开始通信了。程序中服务器监听到来自客户端的请求后,首先发送一条Welcome信息,然后阻塞等待客户端的数据,接收到客户端的数据后,服务器在前面加上Hello,并将消息发送给客户端。如果客户端发送"exit"串,则关闭服务器和客户端的连接。

3. 客户端

为测试服务器程序,我们编写了一个简单的客户端程序:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接:
s.connect(('127.0.0.1', 9999))
# 接收欢迎消息:
print(s.recv(1024).decode('utf-8'))
for data in [b'Michael', b'Tracy', b'Sarah']:
    # 发送数据:
    s.send(data)
    print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()

4. 运行结果

服务器端

 

 客户端

 

需要注意的是,客户端运行完成后就直接退出,而由于服务器维持着一个长连接,必须手动强制关闭程序。

【参考资料】

[1] 廖雪峰, TCP编程.

 

原文地址:https://www.cnblogs.com/lemonu/p/8806451.html