IP地址标识电脑,端口标识程序
一种通信手段
套接字用完一定要关闭
sendto 两个参数内容为bytes类型的,IP是字符串,端口是数字
recvfrom()括号里面加1024的倍数,表示接收长度
绑定端口:bind()里面加元组,IP加端口
IP为空表示绑定本机的所有ip,如果填了某一个IP表示绑定了某一张网卡,只能接受这一网卡的消息。但是127.0.0.1绑定后,只能是本机给本机发送消息(其他人是发送不了的,因为此IP表示的是自己的电脑)
理解UDP与TCP两种套接字的 不同点
理解send recv函数的功能
理解服务器中bind listen accpet 函数的功能
简称:传输控制协议(Transmission Control Protocol)
特点:面向连接、可靠传输、*基于字节流(讲完之后就明白了,暂时忽略)
步骤:创建连接,数据传送,终止连接
使用场景:HTTP / HTTPS / FTP
QQ文件传输
浏览器
面向连接
建立链接/通信/关闭链接
可靠传输
应答机制ACK
超时重传
错误校验,奇偶校验(00010110最后一个“0”前面每一位看看加起来是不是原 先的奇数或偶数)
拥塞控制 根据实时情况调整发送速度
*基于字节流
最小单位是字节 可能造成的现象:多次发送一次接收的线程
这次没有接收完的(超过了最大长度,超出的下次接收)会在下次接收,并不会消失
TCP对比UDP(重点)
可靠 --不可靠
面向连接 --面向无连接
保证顺序 --不保证发送包的顺序和接收顺序是一致的
不支持广播 --UDP支持广播
字节流协议 --用户数据报协议
import socket
# 两个参数 第二个是字节流类型
tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 创建和服务器的连接 参数是服务器地址(ip,端口)
data = input("请输入你要发送的内容:")
ip = input("ip:")
port = int(input("端口:"))
tcp_socket.connect((ip,port))
# send(bytes类型数据)
tcp_socket.send(data.encode())
tcp_socket.close()
#接收数据
recv_data = tcp_socket.recv(1024)
print(recv_data.decode())
#接收数据
recv_data = tcp_socket.recv(1024)
# if recv_data == b'':
if not recv_data:
print("对方断开了连接,,,,,,,,")
else:
print(recv_data.decode('gbk'))
创建 套接字对象 = socket(AF_INET,SOCK_STREAM)
链接 套接字对象.connect((服务器IP,端口))
IP与端口是一个元组,记得写括号
接收 bytes类型数据 = 套接字对象.recv(本次接收的最大长度)
如果接受的是来自Windows服务器的数据,需要转换成gbk格式
recv_data.decode('gbk')
只有数据,没有地址,因为一开始就建立了链接
如果对方断开了链接 数据为空字节b' '
否则就是 通信的数据
发送 套接字对象.send(data.encode())
括号里为bytes类型的数据
关闭 套接字对象.close()
import socket
# 1 总机 - 创建TCP套接字<服务器套接字 监听套接字>
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2 固定号码 - 固定端口
server_socket.bind(('', 10010))
# 3 安装客户服务系统 - 主动-> 被动监听模式
server_socket.listen(128) #128表示有128个接通但是没没被服务过的
# 4 从等待服务区取出一个客户端用以服务 转接到分机 - 接受连接 accept 接受连接
# (和客户端关联起来的套接字对象<socket.socket>, 客户端套接字地址('192.168.33.110', 46080))
client_socket, client_address = server_socket.accept()
print("接受到了来自%s的连接请求" % str(client_address))
while True:
# 5 使用分机进行深入交流 echo回射
recv_data = client_socket.recv(1024)
print("接收到了数据:%s" % recv_data.decode())
client_socket.send(recv_data)#回射服务器
if not recv_data:
print("客户端下线了")
break
# 6 分机挂机
client_socket.close()
# 7 总机挂机
server_socket.close()
改进代码
import socket
# 1 总机 - 创建TCP套接字<服务器套接字 监听套接字>
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2 固定号码 - 固定端口
server_socket.bind(('', 10010))
# 3 安装客户服务系统 - 主动-> 被动监听模式
server_socket.listen(128)
while True:
# 4 从等待服务区取出一个客户端用以服务 转接到分机 - 接受连接
# (和客户端关联起来的套接字对象<socket.socket>, 客户端套接字地址('192.168.33.110', 46080))
client_socket, client_address = server_socket.accept()
print("接受到了来自%s的连接请求" % str(client_address))
while True:
# 5 使用分机进行深入交流 echo回射
recv_data = client_socket.recv(1024)
print("接收到了数据:%s" % recv_data.decode('gbk'))
client_socket.send(recv_data.decode('gbk').encode())
if not recv_data:
print("客户端下线了")
break
# 6 分机挂机
client_socket.close()
# 7 总机挂机
server_socket.close()
百度网盘、邮件等都是TCP的例子
import socket
# 1.建立和服务器的连接
# 1.1用户输入ip地址和端口
IP = input("服务器ip:")
port =int( input("服务器端口:"))
# 1.2创建tcp的套接字
tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 1.3连接服务器
tcp_socket.connect((IP,port))
# 2.向服务器发送需要下载的文件名称
# 2.1用户输入文件名称
file_name = input("需要下载的文件名称:")
# 2.2发送
tcp_socket.send(file_name.encode())
# 3.一边接收文件数据,一边写入文件 完后:关闭套接字 文件
# 3.1打开文件用于保存 接收到的数据(文件的大小一般是1024或整数倍
# ,太大没用,网卡有限制,4k/16左右就可以了)
file = open("下载" + file_name,"wb") # 为了减少代码,方便统一,全为二进制
while True:
# 3.2接收数据,写入文件
file_data = tcp_socket.recv(4096)
# 3.3如果数据是‘’传输完成 关闭文件 套接字 ; 否则继续3.2步骤
if not file_data:
print("文件下载完成.....")
file.close()
tcp_socket.close()
break
file.write(file_data)
流程:
1创建服务器套接字 --->2 绑定端口 监听 ----> 3接受链接请求 ----> 4接受到来自客户端的文件名 ----> 5根据文件名读取文件数据 ----> 6发送文件数据 ----> 7关闭文件 ----> 8关闭套接字 ----> 9再执行第4步
import socket
def main():
# 1 接受用户的连接请求
# 1.1 创建服务器套接字 -- 接受请求,将请求转接到客户端关联的套接字上去
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 1.2 绑定端口 让别人发现我们
server_socket.bind(('', 1111))
# 1.3 监听
server_socket.listen(128) # 128是一个经验值,记住,常用
while True:
# 1.4 接受连接 返回值是元祖(客户端关联的套接字对象,客户端地址)
client_socket, client_address = server_socket.accept()
print("接受到来自%s的连接请求" % str(client_address))
# 2 接收文件名称 -
# 2.1使用和客户端关联的套接字对象 接收数据
file_name = client_socket.recv(4096)
if not file_name:
print("客户端断开连接......")
client_socket.close()
continue
# 2.2文件名解码称str类型
file_name = file_name.decode()
# 3 根据文件名称 读取文件数据 发送给客户端
# 3.1打开指定文件名称的文件 用以读取
with open(file_name,"rb") as file:# 读完之后交给with自动关闭,记住语法
# 3.2(边读边发)这里比较小,直接读取出整个文件的数据
file_data = file.read() # 如果文件大,可能存在程序奔溃的风险
# file.close()
# 3.3 将数据发送给客户端
client_socket.send(file_data)
# 4 如果传输完成 关闭文件,关闭套接字
client_socket.close()
if __name__ == '__main__':
main()
三次握手目的:建立链接
SYN同步请求--建立链接的请求 seq代表序号
ACK应答
ACK再次应答
SYN=1 1代表这个包有同步请求的功能 大写的ACK代表着标志,标志之一代表设置
ack=J + 1 代表收到了
对于服务器必须三次握手,已经完成三次握手的连接,称为全连接
未完成三次握手的连接,称为半连接
listen可以实现将半连接和全连接分成两类,分别存放在不同的空间
listen(128)作用
1 主动 -> 监听
2 参数含义,Linux中表示已就绪队列长度,其他平台一般表示二者综合
(128单位是个,表示最多容纳128个客户端,其他人再链接就连不上了)
accept作用
从已就绪队列中取出一个全连接用以通信
connect作用
发起并且完成和服务器之间的三次握手 建立连接
FIN表示完成
除非双方都断开才能完成断开链接,只有一端断开是完不成的
主动端和被动端
意义:忽略2MSL时间(进行补充)
目的:解决前面历史遗留问题
现象:服务器立即重启出现。Address in use地址使用中
表面原因:TCP标准规定了 凡是主动断开连接的一方,必须保持该连接资源一端时间2MSL而不被释放 2MSL时间:30s到2min
深层原因:为了更加彻底断开TCP连接
最后一次ACK可能会丢失
解决问题:使用地址重用选项--忽略2MSL时间
套接字对象.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
先导入time模块
time.strftime('%Y-%m-%d %H:%M:%S')
上面的结果可以直接使用字符串进行接收
import socket
tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_socket.connect(("192.168.191.5",10086))
print("欢迎使用TCP通信软件".center(36,'='))
print("小闫出品,必属精品".center(35,'-'))
while True:
b = input("请输入你要问的问题:")
if not b:
print("欢迎下次使用")
break
tcp_socket.send(b.encode())
a = tcp_socket.recv(1024)
print("智能机器人回复您:%s" % a.decode())
print('='*40)
import socket
import time
"""
1.自己写tcp客户端以及服务端
2.发送"你好"、"hello"等,会回复"你好"
3.发送"名字"、"name"等关键词,会回复"我是python29号"
4.发送"时间"、"time"等关键词,会回复"当前时间是:xx:xx:xx(当前时间)"
提示:显示时间:time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
可简写为:time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
可简写为:time.strftime('%Y-%m-%d %H:%M:%S')
……自行添加
"""
server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
server_socket.bind(('',10086))
server_socket.listen(128)
client_socket,client_adress = server_socket.accept()
print("%s连接了您" % str(client_adress))
while True:
new_data = client_socket.recv(1024)
data = new_data.decode()
if "你好" in data or"hello" in data:
client_socket.send('你好'.encode())
elif "名字" in data or"name" in data:
client_socket.send('我是python29号'.encode())
elif "时间" in data or "time" in data:
client_socket.send(time.strftime('%Y-%m-%d %H:%M:%S').encode())
elif not data:
print("下线")
break
else:
client_socket.send("我不能明白您的意思,好尴尬啊...".encode())
client_socket.close()
import socket
import random
"""
实现局域网内的点对点聊天机器人程序。
使用TCP协议编写 socket 程序,分别实现消息的发送端和接收端
服务端记录客户端发送的消息,并进行随机回复
当客户端发送Bye时结束聊天
"""
def main():
tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
tcp_socket.bind(('',10086))
tcp_socket.listen(128)
list = []
while True:
client_socket,client_address = tcp_socket.accept()
print("与%s建立连接...." % str(client_address))
while True:
data = client_socket.recv(1024)
new_data = data.decode()
list.append(new_data)
n = random.randint(0,(len(list)-1))
client_socket.send(list[n].encode())
if not data:
print("客户端断开连接...")
break
client_socket.close()
if __name__ == '__main__':
main()
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有