PYTHON中TCP服务器代码的编写。

来源:互联网 发布:网站域名备案要多久 编辑:程序博客网 时间:2024/05/29 18:25

TCP相关的介绍
UDP通信模型中,在通信开始之前,不需要建立相关的链接,只需要发送数据即可
他们的运作流程如下图所示

http://img.blog.csdn.net/20170613231326590?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzE5Mjc3ODU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

在TCP通信模型中,在通信之前,一定好建立链接才能发送数据类似于生活中的打电话。

在下面中示意图中tcp相比udp有connect这个流程
这里写图片描述

怎样完成一个tcp的服务器的代码的编写呢。
为了掩饰这个服务代码有没有成功,我特意的找到一个客户端来演示一下,打印的结果如图所示.由于本人的代码是mac所以找到xsocket的app

这里写图片描述

import socket#创建套接字s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#绑定端口和ip穿进去的是一个元祖s.bind(('',8899))#有主动套接字,这个值表示已建立,未建立套接字的总长度,s.listen(5)#clientSocket表示这个新的客户端,clientSocket,clientInfo = s.accept()#在这个新的套接字来接受用户的 数据recvData = clientSocket.recv(1024)print('%s:%s'%(str(clientInfo),recvData.decode('utf8')))s.close()clientSocket.close()

其实上面的代码我只演示服务器的接收数据,执行上面的代码,我们发现只能执行一次,为了执行多次我们需要在接受数据的循环。

单进程TCP服务器

import socketserSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#重复使用拷贝绑定信息;serSocket.setsockopt(socket.SOL_SOCKET,socket.SOCK_STREAM,1)localAddr = ('',7799)serSocket.bind(localAddr)serSocket.listen(5)while True:    print('主线程等待新的客户端进来')    newSocket,destAddr = serSocket.accept()    try:        while True:            recvData = newSocket.recv(1024)            if len(recvData)>0:                print('recv[%s]:%s'%(str(destAddr),recvData))    finally:        newSocket.close()

上述代码,有一个缺陷是这是一个单进程的TCP服务器,如果客户端不关闭socket,那么其他客户端永远将链接不进来,确实有很多的局限性
为了解决这个问题,胆码进一步演进一下,这次我利用多进程,去创建一个newSocket这个对象,来处理与客户端的交互。

———————————*多进程TCP服务器**—————————————-
多进程TCP服务器代码示例

import socketfrom multiprocessing import *from time import sleep#处理客户端请求,并为其提供服务def dealWithClient(newSocket,destAddr):    while True:        recvData = newSocket.recv(1024)        if len(recvData)>0:            print('recv[%s]:%s'%(str(destAddr),recvData))        else:            print('[%s]客户端已经关闭'%str(destAddr))        break    newSocket.close()def main():    serSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)    serSocket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)    localAddr = ('',7779)    serSocket.bind(localAddr)    serSocket.listen(5)    try:        while True:            print('主进程===等待新的客户端进来')            newSocket,DestAddr = serSocket.accept()            print('主进程接下来创建一个新的进程来执行与客户端的交互')            client = Process(target=dealWithClient,args=(newSocket,DestAddr))            client.start()            #因为子进程已经拷贝了一份newsocket,所以可以关闭            newSocket.close()    finally:serSocket.close()if __name__ == '__main__':    main()

上面是一个多进程TCP服务器的代码的编写,可以一次链接多个tcp客户端,其实还一种方式来实现一次链接多个客户端的方法,那就是使用python多线程,与代码和多进程类似,在多多进程中,我们讲处理与客户单交互的函数放在子进程中,多线程的tcp服务器就是放在子线程中而已

import socketfrom threading import Threadfrom time import sleepdef dealWithClient(newSocket,destAddr):    while True:        recvData = newSocket.recv(1024)        if len(recvData)>0:            print('recv[%s]:%s'%(str(destAddr),recvData))        else:            print('[%s]客户端已经关闭'%str(destAddr))        break    newSocket.close()def main():    serSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)    serSocket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)    localAddr = ('',7777)    serSocket.bind(localAddr)    serSocket.listen(5)    try:        while True:            print('主进程===等待新的客户端进来')            newSocket,DestAddr = serSocket.accept()            print('主进程接下来创建一个新的线程来执行与客户端的交互')            client = Thread(target=dealWithClient,args=(newSocket,DestAddr))            client.start()            #因为线程中共享这个套接字,如果关闭了导致这个套接字不可用            newSocket.close()    finally:serSocket.close()if __name__ == '__main__':    main()

但是能不能在单进程的服务器内创建一个可以实现一个可以连接多个客户端的服务器。答案是可以的 ,我们只需要将serverSocket设置为非阻塞的就可以了,当然设置成非阻塞的有一个问题是当我们需要这个套接字的时候,这个套接字还没有创建,所以我们在这里要try一次

import socketdef main():    #创建套接字    serSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)    serSocket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)    localAddr = ('',7777)    serSocket.bind(localAddr)    # 设置一个套接字属性;    serSocket.setblocking(False)    serSocket.listen(5)    # 用来保存所有连接的客户单    serSocketList = []    while True:        # 等待新的一个客户端的到来        # newSocket,destAddr = serSocket.accept()        try:            newSocket,clientAddr = serSocket.accept()            newSocket.setblocking(False)            serSocketList.append((newSocket,clientAddr))        except:            pass        else:            print('一个新的客户端到来%s'%clientAddr)        for newSocketj,clientAddr in serSocketList:            try:               recvData= newSocket.recv(1024)            except:                pass            else:                if len(recvData):                    print('%s:%s'%(str(clientAddr),recvData))                else:                    newSocket.close()                    serSocketList.remove((newSocket,clientAddr))                    print('%s:已经下线'%(str(clientAddr)))if __name__ == '__main__':    main()

上述代码都是基于python3,都运行成功后才粘贴上来的,本篇博客还会去持续的更新。