推荐链接:‘网络编程’
服务端一直是监听状态的。 客户端单工通信请求连接服务端,服务端通过然后请求客户端建立连接,单工。客户端接收到通过并回复。然后建立起双工通信。合并了2,3条信息有收必有发,收发必相等。
断开可以是客户端也可以是服务端先。 建立连接后,后面的发送是基于连接下发送消息。即使没有连接,服务端和客户端也可以互发消息的。 --- import socket sk = socket.socket() sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 sk.listen() #监听连接,个数 conn,addr = sk.accept() #接受客户端连接,阻塞 ret = conn.recv(1024) #接收客户端信息 print(ret) #打印客户端信息 conn.send(b'hi') #向客户端发送信息 conn.close() #关闭客户端套接字 sk.close() #关闭服务器套接字(可选)- 创建对象, 绑定ip端口 监听
accept和connect实现了三次握手的过程
conn.close()和sk.accept().close区别:
conn.close()为了断开单个连接的客户端 sk.accept().close服务端断开,所有客户端都连接不上了 ------- bind ip 端口 ip为127的只能自己访问,IP为自己的ip可以提供给他人访问 --- sk.send("".encode())这里编码是啥,服务端ret = conn.recv(1024)就要解码 ret.decode sk.send(b""),服务端ret = conn.recv(1024) 收发对应上 ------- input实现聊天。 发送消息为input信息 服务端conn.send(b'hi') ret = conn.recv(1024) ---- 为了实现多次聊天 将input消息发送消息,接收打印消息放入死循环 关闭和accept都不能在死循环里。为了实现退出聊天,加个对输入消息的判断,退出死循环:
客户端发送退出,服务端接收到的就退出, 服务端发送退出,服务端退出循环就直接关闭连接然后关闭sk,客户端报错 外层再加个while循环,内层循环在conn,addr = sk.accept(),conn.close() 直接,这样关闭一个连接,那么可以进行下一个连接: ---- ret=sk.send(input(">>>").encode("utf-8"))如果有变量接收,那么自动打印ret字节长度 ------- input在这里只能实现一来一回多人能同时聊天,同时互连,发消息给谁-服务端进行转发
sk.listen(n)允许多少个人等待 -----udp 服务端recvfrom这样知道是谁发的, 客户端recv就可以,因为已经知道是发给谁,只要内容就可以了tcp不能1对多因为占线了,双层循环
udp实现了服务端1对多(聊天)(加上识别身份)--------udp创建
udp服务端: import socket udp_sk = socket.socket(type=socket.SOCK_DGRAM) #创建一个服务器的套接字 udp_sk.bind(('127.0.0.1',9000)) #绑定服务器套接字 while True: msg,addr = udp_sk.recvfrom(1024) if msg.decode("utf-8").upper()=="Q":break print(msg.decode()) a=input(">>>").encode("utf-8") udp_sk.sendto(a,addr) # 对话(接收与发送) if a.decode().strip(">>>").upper() == "Q": break udp_sk.close()udp客户端:
import socket udp_sk = socket.socket(type=socket.SOCK_DGRAM) #创建一个服务器的套接字 udp_sk.bind(('127.0.0.1',9000)) #绑定服务器套接字 while True: msg,addr = udp_sk.recvfrom(1024) if msg.decode("utf-8").upper()=="Q":break print(msg.decode()) a=input(">>>").encode("utf-8") udp_sk.sendto(a,addr) # 对话(接收与发送) if a.decode().strip(">>>").upper() == "Q": break udp_sk.close()udp服务端:
创建一个udp对象加参数type=socket.SOCK_DGRAM, 对象.bind绑定ip端口 接收信息 对象.recvfrom(字节数) 发送信息 对象.sendto(字节类型数据) 关闭对象 对象.closeudp客户端:
创建一个udp对象加参数socket.socket(type=socket.SOCK_DGRAM) 发送给谁:对象.sendto(字节内容,ip端口元组) 接收信息:对象.recv(字节数) 不需要关闭,udp对象没有关闭方法。1)二者接收到的内容显示一下
2)想不断接收发送那就将接收数据发送数据放到while循环 3)想停止客户端while循环那就判断发送的指定字符为Q退出循环 4)客户端退出while循环停止服务端跟随停那么服务端判断接收到指定字符Q,break循环 5)服务端突然停6)想退出while循环可以写成一行:if a.decode().strip(">>>").upper()=="Q":break
7)服务端未开或服务端突然停止,客户端发送数据报错:[WinError 10054] 远程主机强迫关闭了一个现有的连接。 8)服务端突然停止,客户端在等待服务端回复,似乎客户端会卡住,不退出,输入内容因为不是在发送阶段所以没反应 9)如果想服务端和客户端有个想要退出Q,那么都是在自己这里发送之后判断发送是否为Q,在对方接收后面打印接收之前就可以判断是否为Q,是则breck循环。一般两方都停的适用于tcp的连接。 10)如果想给每个和服务端通话的客户端加个标签,那么只需要将客户端发送的数据加个标签 11)udp没有服务端没有listen监听端口,它可以服务端1对多通信。给每个客户端加个name,将name发送出去以识别是谁 12)客户端 sendto忘记加IP端口元组,报错:sendto() takes 2 or 3 arguments (1 given) 13)服务端sendto(字节内容,ip端口元组),[1]客户端 对象.recvfrom(1024)接收到的是个元组(字节内容,ip端口元组)[2]客户端 对象.recv(1024)接收到的是字节内容,比如:b'2'报错:
1) 2) 3)udp服务端,udp客户端,将客户端的(type=socket.SOCK_DGRAM)改为()报错: OSError: [WinError 10057] 由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。sendto的问题:
正确1:服务端udp_sk.sendto(a,addr) 客户端: back_msg,addr=udp_sk.recvfrom(1024) 正确2:服务端:udp_sk.sendto(a,addr) 客户端:back_msg=udp_sk.recv(1024) 1)服务端: udp_sk.send(a,addr) 客户端 back_msg,addr=udp_sk.recvfrom(1024) 报错:TypeError: an integer is required (got type tuple) 2)服务端:udp_sk.send(a) 客户端 back_msg,addr=udp_sk.recvfrom(1024) 报错:OSError: [WinError 10057] 由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。 3)服务端:udp_sk.sendto(a) 客户端:back_msg,addr=udp_sk.recvfrom(1024) 报错:TypeError: sendto() takes 2 or 3 arguments (1 given) 4)服务端:udp_sk.sendto(a,addr) 客户端:back_msg,addr=udp_sk.recv(1024) 客户端报错:ValueError: not enough values to unpack (expected 2, got 1)综上:udp用sendto,发送内容和IP端口组成的元组,接收用recvfrom则接收两个内容,用recv只是接收发送的数据。
TCP
tcp连接:
import socketsk = socket.socket()sk.bind(('127.0.0.1',9000)) #把地址绑定到套接字sk.listen() #监听链接conn,addr = sk.accept() #接受客户端链接ret = conn.recv(1024) #接收客户端信息print(ret) #打印客户端信息conn.send(b'hi') #向客户端发送信息conn.close() #关闭客户端套接字sk.close() #关闭服务器套接字(可选)-----结果:b'hello!'import socketsk = socket.socket() # 创建客户套接字sk.connect(('127.0.0.1',9000)) # 尝试连接服务器sk.send(b'hello!')ret = sk.recv(1024) # 对话(发送/接收)print(ret)sk.close() # 关闭客户套接字------------结果:b'hi'
tcp连接实现一直通话
import socketsk = socket.socket()sk.bind(('127.0.0.1',9000)) #把地址绑定到套接字sk.listen() #监听链接conn, addr = sk.accept() # 接受客户端链接。产生一个阻塞。时while True: ret = conn.recv(1024).decode("utf-8") #接收客户端信息 print(ret) #打印客户端信息 msg=input(">>>") conn.send(msg.encode("utf-8")) #向客户端发送信息conn.close() #关闭客户端套接字sk.close() #关闭服务器套接字(可选)----------结果:c1>>>s1c2>>>import socketsk = socket.socket() # 创建客户套接字sk.connect(('127.0.0.1',9000)) # 尝试连接服务器while True: msg=input(">>>") sk.send(msg.encode("utf-8")) ret = sk.recv(1024).decode("utf-8") # 对话(发送/接收) print(ret)sk.close() # 关闭客户套接字---------结果:>>>c1s1>>>c2
tcp退出一直聊天
import socketsk = socket.socket()sk.bind(('127.0.0.1',9000)) #把地址绑定到套接字sk.listen() #监听链接conn, addr = sk.accept() # 接受客户端链接while True: ret = conn.recv(1024).decode("utf-8") #接收客户端信息 if ret.upper()=="Q":break print(ret) #打印客户端信息 msg=input(">>>") conn.send(msg.encode("utf-8")) #向客户端发送信息 if msg.upper()=="Q":breakconn.close() #关闭客户端套接字sk.close() #关闭服务器套接字(可选)------------结果:c1>>>c2Process finished with exit code 0import socketsk = socket.socket() # 创建客户套接字sk.connect(('127.0.0.1',9000)) # 尝试连接服务器while True: msg=input(">>>") sk.send(msg.encode("utf-8")) if msg.upper()=="Q":break ret = sk.recv(1024).decode("utf-8") # 对话(发送/接收) if ret.upper()=="Q":break print(ret)sk.close() # 关闭客户套接字----------------结果:>>>c1c2>>>qProcess finished with exit code 0
tcp连接,退出一个连接后可以进入下一个连接:
import socketsk = socket.socket()sk.bind(('127.0.0.1',9000)) #把地址绑定到套接字sk.listen() #监听连接,允许等待的个数while True: conn, addr = sk.accept() # 接受客户端连接 while True: ret = conn.recv(1024).decode("utf-8") #接收客户端信息 if ret.upper()=="Q":break print(ret) #打印客户端信息 msg=input(">>>") conn.send(msg.encode("utf-8")) #向客户端发送信息 if msg.upper()=="Q":break conn.close() #关闭客户端套接字sk.close() #关闭服务器套接字(可选)import socketsk = socket.socket() # 创建客户套接字sk.connect(('127.0.0.1',9000)) # 尝试连接服务器while True: msg=input(">>>") sk.send(msg.encode("utf-8")) if msg.upper()=="Q":break ret = sk.recv(1024).decode("utf-8") # 对话(发送/接收) if ret.upper()=="Q":break print(ret)sk.close() # 关闭客户套接字
tcp连接不同的用户不同的名字识别:
import socketsk = socket.socket()sk.bind(('127.0.0.1',9000)) #把地址绑定到套接字sk.listen() #监听连接,允许等待的个数while True: conn, addr = sk.accept() # 接受客户端连接 while True: ret = conn.recv(1024).decode("utf-8") #接收客户端信息 if ret.upper()=="Q":break print(ret) #打印客户端信息 msg=input(">>>") conn.send(msg.encode("utf-8")) #向客户端发送信息 if msg.upper()=="Q":break conn.close() #关闭客户端套接字sk.close() #关闭服务器套接字(可选)--------结果:小马过河1234QQ:xiao>>>q小郭吹雪1234QQ:ming>>>import socketsk = socket.socket() # 创建客户套接字sk.connect(('127.0.0.1',9000)) # 尝试连接服务器name_and_qq="小郭吹雪1234QQ"while True: msg=input(">>>") sk.send((name_and_qq+":"+msg).encode("utf-8")) if msg.upper()=="Q":break ret = sk.recv(1024).decode("utf-8") # 对话(发送/接收) if ret.upper()=="Q":break print(ret)sk.close() # 关闭客户套接字
1.基于tcp协议实现聊天基础需求:
# 1.server和client端连接之后,能知道对面这个人是哪一个好友 qq号# 2.不同好友的聊天颜色不同 https://www.cnblogs.com/Eva-J/p/8330517.html
import randomimport socketsk = socket.socket()sk.bind(('127.0.0.1',9000)) #把地址绑定到套接字sk.listen() #监听连接,允许等待的个数while True: color=random.randint(30,37) color="\033[amb\033[0m".replace("a",str(color)) conn, addr = sk.accept() # 接受客户端连接 while True: ret = conn.recv(1024).decode("utf-8") #接收客户端信息 if ret.upper()=="Q":break print(color.replace("b",ret)) #打印客户端信息 msg=input(">>>") conn.send(msg.encode("utf-8")) #向客户端发送信息 if msg.upper()=="Q":break conn.close() #关闭客户端套接字sk.close() #关闭服务器套接字(可选)# ----------结果:# 小马过河1234QQ:xiao# >>>q# 小郭吹雪1234QQ:ximgn# >>>import socketsk = socket.socket() # 创建客户套接字sk.connect(('127.0.0.1',9000)) # 尝试连接服务器name_and_qq="小马过河1234QQ"while True: msg=input(">>>") sk.send((name_and_qq+":"+msg).encode("utf-8")) if msg.upper()=="Q":break ret = sk.recv(1024).decode("utf-8") # 对话(发送/接收) if ret.upper()=="Q":break print(ret)sk.close() # 关闭客户套接字