Socket(套接字) 套接字是一個抽象層,應用程式可以通過它發送或接收數據,可對其進行像文件一樣的打開、讀寫和關閉等操作。套接字允許應用程式將I/O插入到網路中,並與網路中的其他應用程式進行通信。網路套接字是IP地址與埠的組合。 發展:套接字最初是由加利福尼亞大學Berkely分校為Unix系統 ...
Socket(套接字)
套接字是一個抽象層,應用程式可以通過它發送或接收數據,可對其進行像文件一樣的打開、讀寫和關閉等操作。套接字允許應用程式將I/O插入到網路中,並與網路中的其他應用程式進行通信。網路套接字是IP地址與埠的組合。
發展:套接字最初是由加利福尼亞大學Berkely分校為Unix系統開發的網路通信介面。後來隨著TCP/IP網路的發展,套接字成為最為通用的應用程式介面,也是在Internet上進行應用開發最為通用的API.
應用:
實現:
基於TCP協議實現Sever端和Client端的信息互通
Sever端:
import socket sk = socket.socket() #創建伺服器的套接字 sk.bind(('127.0.0.1',8080)) #把地址綁定到套接字 sk.listen() #監聽鏈接 conn,addr = sk.accept() #接收到客戶端的連接和地址 ret = conn.recv(1024) #接收客戶端信息 print(ret) #列印客戶端的信息 conn.send(b'hi') #向客戶端發送信息 conn.close() #關閉客戶端的連接 sk.close() #關閉伺服器套接字
Client端:
import socket sk = socket.socket() #創建客戶端的套接字 sk.connect(('127.0.0.1',8080)) #嘗試連接伺服器 sk.send(b'hello') #向伺服器發送消息 ret = sk.recv(1024) #接收伺服器發送的消息 print(ret) #列印伺服器發送的消息 sk.close() #關閉客戶端的套接字
Sever端和Client端兩邊都要對應接收和發送信息,不能只接不收或只收不接且執行時要先執行Sever端再去執行Client端,執行結果:
當重啟伺服器時遇到地址已被使用的問題
解決方案:
如何讓客戶端和伺服器能夠多次進行對話?
Sever端:
import socket from socket import SOL_SOCKET,SO_REUSEADDR sk = socket.socket() #創建伺服器的套接字 sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) sk.bind(('127.0.0.1',8080)) #把地址綁定到套接字 sk.listen() #監聽鏈接 conn,addr = sk.accept() #接收到客戶端的連接和地址 print(addr) #列印客戶端的地址 ret = conn.recv(1024) #接收客戶端信息 print(ret) #列印客戶端的信息 conn.send(b'hi') #向客戶端發送信息 print(addr) #列印客戶端的地址 ret = conn.recv(1024) #接收客戶端信息 print(ret) #列印客戶端的信息 conn.send(b'hi') #向客戶端發送信息 conn.close() #關閉客戶端的連接 sk.close() #關閉伺服器套接字
Client端:
import socket sk = socket.socket() #創建客戶端的套接字 sk.connect(('127.0.0.1',8080)) #嘗試連接伺服器 sk.send(b'hello') #向伺服器發送消息 ret = sk.recv(1024) #接收伺服器發送的消息 print(ret) #列印伺服器發送的消息 sk.send(b'hello') #向伺服器發送消息 ret = sk.recv(1024) #接收伺服器發送的消息 print(ret) #列印伺服器發送的消息 sk.close() #關閉客戶端的套接字
執行結果:
因此我們只要在Sever端獲取到Client端後讓它去迴圈接收和發送消息、讓Client端在連接上Sever端後去迴圈發送和接收消息就能完成一個一直發送接收消息的過程,但這個過程是一個死迴圈,我們需要加上一些條件讓它更加完善
Sever端:
import socket import time from json import dumps from socket import SOL_SOCKET,SO_REUSEADDR sk = socket.socket() #創建伺服器的套接字 sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) sk.bind(('127.0.0.1',8080)) #把地址綁定到套接字 sk.listen() #監聽鏈接 conn,addr = sk.accept() #接收到客戶端的連接和地址 while 1: ret = conn.recv(1024).decode('utf-8') #接收客戶端信息 if ret.strip() == 'bye' or ret.strip() == 'bye'.capitalize(): #跳出迴圈的條件 conn.send(b'bye') #發送bytes類型的Bye print('Client has disconnected!') break print(time.asctime(time.localtime(time.time())) + ' ' + dumps(addr) + ':' + ret) #格式化列印客戶端發來的消息 sendInfo = input(time.asctime(time.localtime(time.time())) + ' <<<') conn.send(sendInfo.encode('utf-8')) #向客戶端發送信息 conn.close() #關閉客戶端的連接 sk.close() #關閉伺服器套接字
Client端:
import socket import time sk = socket.socket() #創建客戶端的套接字 sk.connect(('127.0.0.1',8080)) #嘗試連接伺服器 while 1: sendInfo = input(time.asctime(time.localtime(time.time())) + ' <<<') sk.send(sendInfo.encode('utf-8')) #向伺服器發送消息 ret = sk.recv(1024).decode('utf-8') #接收伺服器發送的消息 if ret.strip() == 'bye' or ret.strip() == 'bye'.capitalize(): #跳出迴圈的條件 sk.send(b'bye') #發送bytes類型的Bye print('Sever has disconnected!') break print(time.asctime(time.localtime(time.time())) + ' ["127.0.0.1", 8080]:' + ret)#格式化列印伺服器發來的消息 sk.close() #關閉客戶端的套接字
執行結果:
基於UDP協議實現Sever端和Client端的信息互通
實現簡單傳遞信息
Sever端:
import socket sk = socket.socket(type=socket.SOCK_DGRAM) #創建伺服器套接字 sk.bind(('127.0.0.1',8080)) #綁定伺服器套接字 msg,addr = sk.recvfrom(1024) #接收到客戶端的信息和地址 print(msg.decode('utf-8')) #將客戶端傳遞來的信息解碼並列印出來 sk.sendto(b'Hello client!',addr) #將bytes類型的信息發送到客戶端的地址 sk.close() #關閉伺服器套接字
Client端:
import socket sk = socket.socket(type=socket.SOCK_DGRAM) #創建客戶端套接字 ip_port = ('127.0.0.1',8080) sk.sendto(b'Hello sever!',ip_port) #客戶端發送信息 ret,addr = sk.recvfrom(1024) #接收到伺服器的地址和信息 print(ret.decode('utf-8')) #列印收到的信息 sk.close() #關閉客戶端套接字
執行結果:
多人版:
Sever端:
import socket sk = socket.socket(type=socket.SOCK_DGRAM) #創建伺服器套接字 sk.bind(('127.0.0.1',8080)) #綁定伺服器套接字 while 1: msg,addr = sk.recvfrom(1024) #接收到客戶端的信息和地址 str_msg = msg.decode('utf-8') print(addr,str_msg) info = input('<<<').encode('utf-8') sk.sendto(info,addr) sk.close() #關閉伺服器套接字
Client1:
import socket sk = socket.socket(type=socket.SOCK_DGRAM) #創建客戶端套接字 ip_port = ('127.0.0.1',8080) while 1: info = input('Client1:') info = ('\033[32m來自Client1的消息:%s\033[0m'%info).encode('utf-8') sk.sendto(info,ip_port) msg,addr = sk.recvfrom(1024) str_msg = msg.decode('utf-8') print(str_msg) sk.close() #關閉客戶端套接字
Client2:
import socket sk = socket.socket(type=socket.SOCK_DGRAM) #創建客戶端套接字 ip_port = ('127.0.0.1',8080) while 1: info = input('Client2:') info = ('\033[36m來自Client2的消息:%s\033[0m' % info).encode('utf-8') sk.sendto(info, ip_port) msg, addr = sk.recvfrom(1024) str_msg = msg.decode('utf-8') print(str_msg) sk.close() #關閉客戶端套接字
執行結果:
udp的Sever不需要進行監聽也不需要建立連接,在啟動服務之後只能被動得等待客戶端發送消息來,客戶端發送消息的同時還會自帶地址信息,消息回覆的時候不僅要發送消息還要把對方的地址給填上