以下为初学者理解:
-
TCP必须区分客户端和服务器,TCP的稳定性比UDP高。
-
比如a向b发送消息,用UDP发送后,你不知道b到底有没有收到消息,而使用TCP发送,b收到消息后服务器会给a一个反馈u信息,a就知道b收到了消息。
-
很多聊天软件,聊天使用的是UDP而发送文件则使用的是TCP。
-
迅雷用的就是TCP,下载东西时你留意下就会发现,会有上传数据,这是怎么回事那?
比如:你要下载一个5G的电影,它会分成很多块发给你进行下载,下载一部分,会给系统一个回传值告诉系统这部分下载好了,然后再发下一部分进行下载,依次类推直到下载完毕。 -
TCP流程图:
# 设置当服务器先close 即服务器端4次挥手之后资源能够立即释放,这样就保证了,下次运行程序时 可以立即绑定7788端口
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
yy_01_tcp客户端
import socket
def main():
# 1.创建tcp套接字
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.链接服务器
server_ip = input("请输入要链接的服务器ip:")
server_port = int(input("请输入要链接的服务器port:"))
server_addr = (server_ip, server_port)
tcp_socket.connect(server_addr)
# 3.发送/接收数据
send_data = input("请输入要发送的数据:")
tcp_socket.send(send_data.encode("utf-8"))
# 4.关闭套接字
tcp_socket.close()
if __name__ == "__main__":
main()
yy_02_tcp服务器
import socket
def main():
# 1.买个手机(创建tcp套接字)
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.插入手机卡(绑定本地信息 bind)
tcp_server_socket.bind(("", 7785))
# 3.将手机设置为正常响铃模式(让默认的套接字由主动变为被动 listen)
tcp_server_socket.listen(128)
print("----1----")
# 4.等待别人的电话到来(等待客户端的链接 accept)
new_client_socket, client_addr = tcp_server_socket.accept()
print("----2----")
print(client_addr)
# 5.接收客户端发过来的请求
recv_data = new_client_socket.recv(1024)
print(recv_data.decode("utf-8"))
# 6.回送一部分数据给客户端
new_client_socket.send("---ok---".encode("utf-8"))
# 7.关闭套接字
new_client_socket.close()
tcp_server_socket.close()
if __name__ == "__main__":
main()
yy_03_循环为多个客户端服务
import socket
def main():
# 1.买个手机(创建tcp套接字)
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.插入手机卡(绑定本地信息 bind)
tcp_server_socket.bind(("", 7785))
# 3.将手机设置为正常响铃模式(让默认的套接字由主动变为被动 listen)
tcp_server_socket.listen(128)
while True:
print("等待一个新发客户端到来")
# 4.等待别人的电话到来(等待客户端的链接 accept)
new_client_socket, client_addr = tcp_server_socket.accept()
print("一个新的客户端来了 %s" % str(client_addr))
# 5.接收客户端发过来的请求
recv_data = new_client_socket.recv(1024)
print("客户端发过来的请求是: %s" % str(recv_data.decode("utf-8")))
# 6.回送一部分数据给客户端
new_client_socket.send("---ok---".encode("utf-8"))
# 7.关闭套接字
# 关闭accept返回的套接字,意味着 不会在为这个客户端服务
new_client_socket.close()
print("服务完毕!")
# 如果将监听套接字关闭,就会导致 不能再次等待新客户的到来, 即xxxx.accept就会失败
tcp_server_socket.close()
if __name__ == "__main__":
main()
yy_04_循环为多个客户端服务,并且多次服务一个客户端
import socket
def main():
# 1.买个手机(创建tcp套接字)
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.插入手机卡(绑定本地信息 bind)
tcp_server_socket.bind(("", 7785))
# 3.将手机设置为正常响铃模式(让默认的套接字由主动变为被动 listen)
tcp_server_socket.listen(128)
while True:
print("等待一个新发客户端到来")
# 4.等待别人的电话到来(等待客户端的链接 accept)
new_client_socket, client_addr = tcp_server_socket.accept()
print("一个新的客户端来了 %s" % str(client_addr))
while True:
# 5.接收客户端发过来的请求
recv_data = new_client_socket.recv(1024)
print("客户端发过来的请求是: %s" % str(recv_data.decode("utf-8")))
if recv_data:
# 6.回送一部分数据给客户端
new_client_socket.send("---ok---".encode("utf-8"))
else:
break
# 7.关闭套接字
# 关闭accept返回的套接字,意味着 不会在为这个客户端服务
new_client_socket.close()
print("服务完毕!")
# 如果将监听套接字关闭,就会导致 不能再次等待新客户的到来, 即xxxx.accept就会失败
tcp_server_socket.close()
if __name__ == "__main__":
main()
yy_05_案例-下载文件(客户端)
import socket
def main():
# 1.创建套接字
tcp_down_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.获取服务器的ip/port
serve_ip = input("请输入下载服务器的ip:")
serve_port = int(input("请输入下载服务器的port:"))
# 3.链接服务器
tcp_down_socket.connect((serve_ip, serve_port))
# 4.获取下载的文件姓名
down_name = input("请输入要下载的文件:")
# 5.将文件名字发到服务器
tcp_down_socket.send(down_name.encode("utf-8"))
# 6.接收文件中的数据 - 是二进制
recv_date = tcp_down_socket.recv(1024*1024) # 1024kb=1k 1024*1024=1k*1024=1M
# 7.保存接收到的数据到一个文件中 - b(bytes)二进制写入
with open("[新]" + down_name, "wb") as f:
f.write(recv_date)
# 8.关闭套接字
tcp_down_socket.close()
if __name__ == '__main__':
main()
yy_06_案例-下载文件(服务器)
import socket
def send_file_2_client(new_client_socket, client_addr): # 2相当与to
# 5.接收客户端发过来的请求
file_name = new_client_socket.recv(1024*1024).decode("utf-8")
print("客户端[%s]需要下载的文件是:%s" % (str(client_addr), file_name))
file_content = None
# 打开文件,读取数据
try:
f = open(file_name, "rb")
file_content = f.read()
f.close()
except Exception as e:
print("没有要下载的文件%s" % file_name)
# 6.发送文件的数据给客户端
if file_content:
new_client_socket.send(file_content)
def main():
# 1.创建套接字
tcp_screct_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.绑定本地信息
tcp_screct_socket.bind(("", 7788))
# 3.让默认的套接字由主动变为被动 listen
tcp_screct_socket.listen(128)
while True:
# 4.等待客户端的链接 accept
new_client_socket, client_addr = tcp_screct_socket.accept()
send_file_2_client(new_client_socket, client_addr)
# 7.关闭套接字
new_client_socket.close()
tcp_screct_socket.close()
if __name__ == '__main__':
main()