《Python高级编程》学习心得——第十章 Python Socket编程

Socket编程原理

下图展示了计算机网络五层模型的框架:

《Python高级编程》学习心得——第十章 Python Socket编程

计算机网络是由一系列协议构成的,其中协议是分层的,最顶层的应用层协议如HTTP,FTP,SMTP支持Web应用如网页浏览、文件传输、邮件发送;次顶层的传输层提供了端对端的连接,主要有TCP和UDP协议,其中大部分Web应用使用的是TCP协议(一直听说早期的QQ使用的是UDP协议,不知是真是假,下次找在鹅厂工作的同学问问);网络层负责寻址和路由,路由器就工作在网络层,涉及的最重要的协议是IP协议;为IP协议提供地址解析的ARP协议工作在数据链路层;最底层的物理层负责为上层提供可靠的物理媒介。

Socket是操作系统提供的一个对传输层的抽象接口,可以使用封装好的TCP/UDP协议,来编写定制的网络应用(类Unix系统也用Socket实现进程之间的通信)。当然,也可以自己用Socket编程的方式实现HTTP等应用层协议实现的功能,不过更简单的方式是调用HTTP协议相关的包来实现。但是,总有些功能不同于HTTP,FTP,SMTP等协议,需要我们自己通过Socket编程来实现,比如即时聊天工具就是一类。不同于HTTP协议中服务端总是响应客户端的请求,即时聊天工具客户端和服务端都具备主动发送数据的能力。

用Socket和多线程实现多客户端连接聊天工具

多客户端连接聊天工具可以模拟真实应用中客服平台等需求,涉及Socket编程(实际应用中会使用Web Socket实现)和多线程的知识,下面直接看代码和注释。值得注意的是Socket发送的是byte,需要对str作编码解码处理。

SocketClient.py

import socket


client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)    # AF_INET: IPV4, SOCK_STREAM: TCP
client.connect(('127.0.0.1', 8000))         # connect localhost:8000

while True:
    re_data = input()                       # wait for user input
    client.send(re_data.encode('UTF-8'))    # send byte data
    if re_data == 'quit':
        break
    ge_data = client.recv(1024)             # receive data
    print(ge_data.decode('UTF-8'))          # decode byte data

client.close()                              # close connection

SocketServer.py

import socket
import threading


def process_client(sock, addr):
    print('Connect client addr: {}'.format(addr))
    while True:
        ge_data = sock.recv(1024)               # receive data
        ge_str = str(ge_data.decode('UTF-8'))
        print(ge_str)
        if ge_str == 'quit':                    # if receive data 'quit', close connect
            print('Disconnect client addr: {}'.format(addr))
            break
        re_data = input()                       # wait for user input
        sock.send(re_data.encode('UTF-8'))      # send byte data
    sock.close()                                # close connection with 


server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)    # AF_INET: IPV4, SOCK_STREAM: TCP
server.bind(('127.0.0.1', 8000))              # bind to localhost:8000
server.listen()                             # listen for clients

while True:
    sock, addr = server.accept()            # accept client
    client_thread = threading.Thread(target=process_client, args=(sock, addr))  # create a client thread
    client_thread.start()                   # start a client thread

server.close()                              # close server

Client ‘HIT’ Console

HIT
Hello, HIT
quit

Client ‘WIT’ Console

WIT
Hello, WIT
quit

Server Console

Connect client addr: ('127.0.0.1', 51776)
HIT
Hello, HIT
Connect client addr: ('127.0.0.1', 51784)
WIT
Hello, WIT
quit
Disconnect client addr: ('127.0.0.1', 51784)
quit
Disconnect client addr: ('127.0.0.1', 51776)

相关文章: