面向連接的tcp 編程
阿新 • • 發佈:2019-03-15
print customer 屬性 設置 建立連接 epo reading bre sleep
from socket import * serverSocket=socket(AF_INET,SOCK_STREAM) serverSocket.bind(("",8899)) serverSocket.listen(5) newSocket,clientAddr=serverSocket.accept() #返回新的套接字和對方的ip地址和端口號 print("有客戶端連接") recvDate=newSocket.revc(1024) print("%s%s"%(str(clientAddr),recvDate)) newSocket.send("thank you !") newSocket.close() serverSocket.close()
from socket import * # 創建socket tcpSerSocket = socket(AF_INET, SOCK_STREAM) # 綁定本地信息 address = (‘‘, 8899) tcpSerSocket.bind(address) # 使用socket創建的套接字默認的屬性是主動的,使用listen將其變為被動的,這樣就可以接收別人的鏈接了 tcpSerSocket.listen(5) # 如果有新的客戶端來鏈接服務器,那麽就產生一個新的套接字專門為這個客戶端服務器# newSocket用來為這個客戶端服務 # tcpSerSocket就可以省下來專門等待其他新客戶端的鏈接 newSocket, clientAddr = tcpSerSocket.accept() # 接收對方發送過來的數據,最大接收1024個字節 recvData = newSocket.recv(1024) print(‘接收到的數據為:%d‘,recvData.decode("gb2312")) # 發送一些數據到客戶端 newSocket.send("thank you !".encode("gb2312")) # 關閉為這個客戶端服務的套接字,只要關閉了,就意味著為不能再為這個客戶端服務了,如果還需要服務,只能再次重新連接newSocket.close() # 關閉監聽套接字,只要這個套接字關閉了,就意味著整個程序不能再接收任何新的客戶端的連接 tcpSerSocket.close()
# 多線程服務器,接收客戶機鏈接 from socket import * from threading import * def recv_send_Thread(customer_sock,addr): while True: str=customer_sock.recv(1024) # 循環接收客戶端發來的信息 customer_sock.send(str) print(str.decode("gb2312")) if str.decode("gb2312") == ‘exit‘: print("關閉套接字") customer_sock.close() break customer_sock.close() #創建服務器的socket server_tcp_socket=socket(AF_INET,SOCK_STREAM) # 解決MSL問題,如果服務器先斷開鏈接,則第四次會後不必等2被時間,即可鏈接,避免出現等到2倍時間內地址被占用的問題 server_tcp_socket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #bind綁定地址和端口 server_tcp_socket.bind(("",8899)) #設置監聽listen server_tcp_socket.listen(5) while True: new_socket,new_addr=server_tcp_socket.accept() #等待接受客戶端鏈接 print(("與客戶%s建立鏈接成功,可以交流" % new_addr[0])) new_socket.send(("您好客戶%s,已經建立鏈接,可以交流" % new_addr[0]).encode("gb2312")) # 鏈接成功後,發送鏈接信息 th=Thread(target=recv_send_Thread,args=(new_socket,new_addr)) th.start() th.join() #收發信息 #釋放鏈接 server_tcp_socket.close()
#select版本的服務器代碼 #輪詢的方式檢測,效率低;32位最多鏈接1023個,64位最多鏈接2045個端口 from socket import * from select import select from sys import * def main(): server = socket(AF_INET,SOCK_STREAM) # 解決MSL問題,如果服務器先斷開鏈接,則第四次會後不必等2被時間,即可鏈接,避免出現等到2倍時間內地址被占用的問題 server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) address = ("",8000) server.bind(address) server.listen(1024) inputs=[server,stdin] running = True while True: readable,writeable,exceptional = select(inputs,[],[]) for sock in readable: if(sock == server): s,addr = server.accept() print(s) inputs.append(s) s.send("已經建立好鏈接".encode("gb2312")) elif sock == stdin: cmd = stdin.readline() running = False break else: msg = sock.recv(1024) print(msg.decode("gb2312")) sock.send(("服務器收到了客戶端發送的:%s"%(msg.decode("gb2312"))).encode("gb2312")) if msg.decode("gb2312")==‘exit‘: #sock.send("將要斷開鏈接".encode("gb2312")) sock.close() inputs.remove(sock) if running==False: break server.close() print("服務器關閉") if __name__ =="__main__": main()
# epool 方式實現服務器 # epool是沒有套接字上限,是時間通知機制。 pool是輪詢機制,解決了套接字有上限的問題。 from socket import * from select import * s = socket(AF_INET,SOCK_STREAM) # 解決MSL問題,如果服務器先斷開鏈接,則第四次會後不必等2被時間,即可鏈接,避免出現等到2倍時間內地址被占用的問題 s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) addr=("",8000) s.bind(addr) s.listen(10) epoll_l = epoll() epoll_l.register(s.fileno(),EPOLLIN|EPOLLET) connections={} addresses={} while True: epoll_list = epoll_l.poll() for fd,events in epoll_list: if fd == s.fileno(): soc,addres = s.accept() soc.send("已經鏈接鏈接".encode("gb2312")) connections[soc.fileno()] = soc addresses[soc.fileno()] = addres epoll_l.register(soc.fileno(), EPOLLIN|EPOLLET) elif events == EPOLLIN: msg = connections[fd].recv(1024) print(msg.decode("gb2312")) connections[fd].send(("收到了客戶端的%s"%msg.decode("gb2312")).encode("gb2312")) if msg.decode("gb2312") == "exit": epoll_l.unregister(fd) connections[fd].close() print() else: pass
# 協程,生成器版本 import time def A(): while True: print("----a----") yield time.sleep(1) def B(c): while True: print("----b----") c.__next__() time.sleep(1) a=A() print(a.__next__()) b=B(a)
# 協程,greenlet版本 from greenlet import greenlet import time def test1(): while True: print("A") gr2.switch() time.sleep(1) def test2(): while True: print("B") gr1.switch() time.sleep(1) gr1=greenlet(test1) gr2=greenlet(test2) gr1.switch()
# gevent版本的服務器 import gevent #from socket import * from gevent import socket,monkey monkey.patch_all() def handle_request(conn): while True: data=conn.recv(1024) if not data: conn.close() break print("recv:%s"%data.decode("gb2312")) conn.send(data) def server(port): s=socket.socket() # 解決MSL問題,如果服務器先斷開鏈接,則第四次會後不必等2被時間,即可鏈接,避免出現等到2倍時間內地址被占用的問題 #s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) s.bind(("",port)) s.listen(5) while True: cli,addr = s.accept() cli.send("已經連接成功".encode("gb2312")) gevent.spawn(handle_request,cli) if __name__=="__main__": server(8000)
客戶端程序:
# 客戶端程序 from socket import * # 創建socket tcpClientSocket = socket(AF_INET, SOCK_STREAM) # 鏈接服務器 serAddr = (‘192.168.249.210‘, 8000) tcpClientSocket.connect(serAddr) # 建立連接 recvData = tcpClientSocket.recv(1024) # 接收數據 print(‘接收到的數據為:‘+recvData.decode("gb2312")) while True: # 提示用戶輸入數據 sendData = input("請輸入要發送的數據:") tcpClientSocket.send(sendData.encode("gb2312")) # 循環發送數據 if sendData == "exit": break # 接收對方發送過來的數據,最大接收1024個字節 recvData = tcpClientSocket.recv(1024) # 循環接收數據 print(‘接收到的數據為:‘+recvData.decode("gb2312")) # 關閉套接字 tcpClientSocket.close()
面向連接的tcp 編程