早先对于python服务器的理解不够充分
对于这门语言的理解一直只处于前端网页的制作与后端数据处理方面
因此对于python服务器的搭建几乎处于空白阶段
对此我表示需要深刻的恶补
因此从头学习python服务器的搭建
结果没想到python服务器处理tcp请求也是使用socket的方式
因此对于我的学习来说还算是比较顺利
1 p_port = ('192.168.7.11', 9999) 2 web = socket.socket() 3 web.bind(ip_port) 4 web.listen(5) 5 6 while True: 7 print 'I am waiting for the client' 8 conn, addr = web.accept() 9 # thread = threading.Thread(target=jonnys, args=(conn, addr)) 10 11 data = conn.recv(1024) 12 print data 13 conn.sendall(str('<h1>welcome nginx</h1>')) 14 conn.close()
以上是简单的服务器
附使用简单客户端
import socket ip_port = ('192.168.7.11', 9999) sk = socket.socket() sk.connect(ip_port) sk.sendall('haha douyu\n') sk.sendall('you like join this\n') server_reply = sk.recv(1024) # server_reply_three = sk.recv(1024) print server_reply # print server_reply_three # sk.sendall('join this\n') # server_reply_two = sk.recv(1024) # print server_reply_two sk.close()
使用ThreadingTCPServer, StreamRequestHandler来实现多线程服务器处理
但是有一个小BUG需要解决
from SocketServer import ThreadingTCPServer, StreamRequestHandler import traceback class MyStreamRequestHandlerr(StreamRequestHandler): """ #StreamRequestHandler,并重写handle方法 #(StreamRequestHandler继承自BaseRequestHandler) """ def handle(self): while True: #客户端主动断开连接时,self.rfile.readline()会抛出异常 try: #self.rfile类型是socket._fileobject,读写模式是"rb",方法有 #read,readline,readlines,write(data),writelines(list),close,flush data = self.rfile.readline().strip() # if data == '\'\'': # print data print "receive from (%r):%r" % (self.client_address, data) # data = self.request.recev(1024).strip #self.client_address是客户端的连接(host, port)的元组) #self.wfile类型是socket._fileobject,读写模式是"wb" self.wfile.write(data.upper()) except: traceback.print_exc() break if __name__ == "__main__": #telnet 127.0.0.1 9999 host = "" #主机名,可以是ip,像localhost的主机名,或"" port = 9999 #端口 addr = (host, port) #ThreadingTCPServer从ThreadingMixIn和TCPServer继承 #class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass server = ThreadingTCPServer(addr, MyStreamRequestHandlerr) #启动服务监听 server.serve_forever()
当客户端主动关闭套接字时
服务器会出现死循环产生子线程来读取空的信息
从而使服务器崩溃
因此诞生第三个版本

# -*- coding: UTF-8 -*- import socket import threading, getopt, sys, string opts, args = getopt.getopt(sys.argv[1:], "hp:l:", ["help", "port=", "list="]) #设置默认的最大连接数和端口号,在没有使用命令传入参数的时候将使用默认的值 list=50 port=9999 def usage(): print """ -h --help print the help -l --list Maximum number of connections -p --port To monitor the port number """ for op, value in opts: if op in ("-l","--list"): list = string.atol(value) elif op in ("-p","--port"): port = string.atol(value) elif op in ("-h"): usage() sys.exit() def jonnyS(client, address): try: #设置超时时间 client.settimeout(500) #接收数据的大小 buf = client.recv(2048) print buf #将接收到的信息原样的返回到客户端中 client.send(buf) #超时后显示退出 except socket.timeout: print 'time out' #关闭与客户端的连接 client.close() def main(): #创建socket对象。调用socket构造函数 #AF_INET为ip地址族,SOCK_STREAM为流套接字 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #将socket绑定到指定地址,第一个参数为ip地址,第二个参数为端口号 sock.bind(('192.168.7.11', port)) #设置最多连接数量 sock.listen(list) while True: #服务器套接字通过socket的accept方法等待客户请求一个连接 client, address = sock.accept() thread = threading.Thread(target=jonnyS, args=(client, address)) thread.start() if __name__ == '__main__': main()
这个版本当服务器与客户端完成通信之后会由服务器关闭套接字
还包括延时功能
因此不会有第二个程序的bug