Socket通信Python实现

Socket通信Python实现

最近开始看一本非常经典的网络教程,计算机网络教程:自顶向下方法,这本书的是从应用层开始写起,相对于以前坑爹的本科生教程更容易令读者感兴趣,并且循循诱导,深入浅出,是本难得的网络教程。

第二章有一个编程作业就是实现简单的Socket通信,这篇文章结合UDP和TCP的原理讲一下相关代码。值得注意的是文章中的代码使用的Python3.6的版本,所有的网络传输默认传递的是二进制比特流,因此采用了utf-8进行编码

1.Socket

Socket中文就是套接字,它是进程和网络之间的通信接口,可以简单认为它就是一个API,一个Socket由IP+Port构成,两个进程间如果需要通过网络通信,那么他们各自需要通过相同的Socket从网络中读/写数据,具体过程可以从下图了解。

Socket通信Python实现_第1张图片
进程通过Socket通信

2.UDP

首先,UDP是一个面向无连接的传输层协议,它在服务器端和客户端的功能没有太大区别,只用创建一个套接字,按照预定的业务或逻辑从套接字中进行读写。文章中UDP通信目的是利用客户端发送小写字符串,服务端将该字符串转换为大写并返回。

Socket通信Python实现_第2张图片
UDP通信过程

2.1 UDP客户端代码

按照UDP通信流程图,首先创建了套接字,设定服务端的IP地址和端口号,并组成Socket。再通过AF_INET设定网络协议为IPv4,SOCK_DGRAM设置传输层使用UDP。

from socket import *
class UdpClient:
    serverName = '127.0.0.1'
    serverPort = 12000
    socketAddress = (serverName, serverPort)
    def __init__(self):
        #define the type of socket is IPv4 and Udp
        self.clientSocket = socket(AF_INET, SOCK_DGRAM)
        while True:
            message = input("Input a lowercase sentence\n")
            self.clientSocket.sendto(message.encode('utf-8'), self.socketAddress)
            returnMessage, serverAddress = self.clientSocket.recvfrom(2048)
            if not returnMessage:
                break
            print("The peersocket is: %s:%s" %(serverAddress[0], serverAddress[1]))
            print("The return message is: %s" %returnMessage.decode('utf-8'))
if __name__ == '__main__':
    client = UdpClient()

2.2 UDP服务端代码

服务端代码和客户端没有太多区别。

from socket import *

serverPort = 12000
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind(('',serverPort))
print('Waiting for connection...')
while True:
    message, clientAddress = serverSocket.recvfrom(2048)
    print('Receive Message: %s' %message.decode('utf-8'))
    modifiedMessage = message.decode('utf-8').upper()
    serverSocket.sendto(modifiedMessage.encode('utf-8'), clientAddress)

3.TCP

TCP是面向连接的传输协议,需要三次握手建立连接,应用需要绑定Socket。相对于UDP多了listenacceptconnect的过程。

Socket通信Python实现_第3张图片
TCP通信流程

3.1 TCP客户端

客户端代码如下,主要实现从服务端返回当前时钟的功能,与UDP的代码相差不大,因为是面向连接,所有需要多一个connect的过程:

from socket import *

serverName = '127.0.0.1'
serverPort = 11000
BUFSIZ = 1024
ADDR = (serverName,serverPort)

clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect(ADDR)

while True:
    data = "client message"
    if not data:
        break
    clientSocket.send(data.encode('utf-8'))
    returnData = clientSocket.recv(BUFSIZ)
    if not returnData:
        break
    print('Return time is:%s' %returnData.decode('utf-8'))
clientSocket.close()

3.2 TCP服务端

服务端主要做了以下工作,首先绑定一个套接字,用于监听客户端的服务请求,同时这里利用listen(5)设定最大的tcp连接数为5,然后进入循环,每次循环记录当前客户端的socket,并处理相应地业务:

from socket import *
from time import ctime

host = ''
port = 11000
ADDR = (host, port)
BUFSIZ = 1024

tcpSocket = socket(AF_INET, SOCK_STREAM)
tcpSocket.bind(ADDR)
#set the max number of tcp connection
tcpSocket.listen(5)

while True:
    print('waiting for connection...')
    clientSocket, clientAddr = tcpSocket.accept()
    print('conneted form: %s' %clientAddr[0])

    while True:
        try:
            data = clientSocket.recv(BUFSIZ)
        except IOError as e:
            print(e)
            clientSocket.close()
            break
        if not data:
            break
        returnData = ctime()+data.decode('utf-8')
        clientSocket.send(returnData.encode('utf-8'))
    clientSocket.close()
tcpSocket.close()

这里是需要先运行server的code,再执行client的code:

➜  Py python3 TcpServer.py
➜  Py python3 TcpClient.py

Client log:

Return time is:Sun Dec 16 17:04:10 2018client message
Return time is:Sun Dec 16 17:04:10 2018client message
...

小结

Socket是网络通信中的一项重要技术,也是一种进程通信的手段,这里列出了一个简单的实现版本,有时间希望可以结合多线程完善该功能。

你可能感兴趣的:(Socket通信Python实现)