一、基础知识
tcp,全称传输控制协议,大致的传输过程是服务器向客户端传输数据时,客户端接收到一部分数据后,会对服务器进行反馈,然后服务器再对客户端传输下一部分数据,当服务器超时未收到客户端收到数据的反馈,则会重新发送数据。这就是为什么在下载文件的时候会有一个上传网速,就是因为客户端要反馈收到数据的信息给服务器。
因此,tcp相对于udp来说,tcp更加稳定,而udp更加简单。现在大多数通信都是用tcp。
udp相当于寄信,tcp相当于打电话,寄信的时候对方不会告诉你收到与否,真正受到信件后如果对方没有回信,则没有办法确定对方是否收到信息。打电话如果对方收到了则可以听到对方反馈回来的声音,没收到则收到“您拨打的用户暂时无法接听”的反馈,则你可重新打电话过去。
二、编程案例
1)编写一个客户端程序,向服务器发送消息或接收服务器的消息。
步骤如下:
a、创建套接字
b、连接服务器
c、发送消息/接收消息
d、关闭套接字
import socket
def main ():
#创建套接字
tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#连接服务器
server_ip = input("服务器的ip是:")
server_port = int(input("服务器的port是:"))
tcp_socket.connect((server_ip,server_port))
#发送消息
send_data = input("请输入你要发送的内容:")
tcp_socket.send(send_data.encode("gbk"))
#接收消息
recv_data = tcp_socket.recv(1024)
print("接收到的信息为:",recv_data.decode("gbk"))
#关闭套节字
tcp_socket.close()
if __name__ == "__main__":
main()
2)编写一个服务器程序,接收客户端的数据并回复消息。步骤如下:
a、创建套接字
b、bind绑定ip和端口号
c、lesten使套接字可以被动连接
d、accept等待客户端连接
e、接收数据,发送数据
f、关闭套接字
import socket
def main():
#创建套接字
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#bind绑定ip和端口号
local_addr = ("",8082)
tcp_server_socket.bind(local_addr)
#listen使套接字被动连接
tcp_server_socket.listen(128)
#accept等待客户端连接
client_socket,client_addr = tcp_server_socket.accept()
#开始循环
while True:
#接收数据
recv_data = client_socket.recv(1024)
#当客户端断开链接时,recv_data的值为空,则根据此条件设置终止循环条件
if recv_data:
print("接收的数据为:",recv_data.decode("gbk"))
else:
break
#发送数据
client_socket.send("我已收到数据".encode("gbk"))
#关闭套接字(这里关闭客户端连接服务器时生成的套接字,意味着为这个客户端服务完毕)
client_socket.close()
#这里关闭整个服务器生成的套接字,意味着服务器不为任何客户端服务)
tcp_server_socket.close()
if __name__ == "__main__":
main()
3)写一个文件下载程序
所谓下载就是服务器的数据发送给客户端,客户端新建一个空文件,接收服务器的数据后,将数据写入空文件中。编写文件下载客户端程序步骤如下:
a、创建套接字
b、获取服务器的ip和端口号
c、连接服务器
d、获取下载文件的名字
e、将文件名字发送给服务器
f、接收文件中的数据
g、将数据写入到文件中
h、关闭套接字
import socket
def main():
#创建套接字
tcp_client_socket = socket(AF_INET,SOCK_ATREAM)
#获取服务器的ip和端口号
server_ip = input("请输入服务器的ip:")
server_port = int(input("请输入服务器的端口号:"))
#连接服务器
tcp_client_socket.connect((server_ip,server_port))
#获取下载文件的名字
download_name = input("请输入需要下载的文件名:")
#将文件名字发送给服务器
tcp_client_socket.send(download_name.encode("utf-8"))
#接收文件中的数据 (1024指的是接收1k的文件)
recv_data = tcp_client_socket.recv(1024)
#将数据写入到文件中
with open("[xin]"+download_name,"wb") as f:
f.write(recv_data)
#关闭套接字
tcp_client_socket.close()
if __name__ == "__main__":
main()
编写文件下载的服务器的程序步骤如下:
a、创建套接字
b、bind绑定ip和端口号
c、listen使套接字被动连接
d、accept等待客户端连接
f、调用发送文件函数发送文件数据给客户端
f1) 接收客户端发送过来需要下载的文件名字
f2) 打开文件,读取数据
f3) 发送数据给客户端
g、关闭套接字
import socket
def send_file_data(new_client_socket):
#接收客户端发送给过来需要下载的文件名字
file_name = new_client_socket.recv(1024).decode("utf-8")
#打开文件并读取数据
file_content=None
try:
f = open(file_name,"rb")
file_content=f.read()
f.close()
except Exception as ret:
print("没有下载的文件(%s)" % file_name)
#发送数据给客户端
if file_content:
new_client_socket.send(file_content)
def main():
#创建套接字
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#bind绑定ip和端口号
local_addr = ("",8080)
tcp_server_socket.bind(local_addr)
#listen使套接字被动连接
tcp_server_socket.listen(128)
#accept等待客户端连接
new_client_socket,new_client_addr = tcp_server_socket.accept()
while True:
#调用发送文件数据发送数据给客户端
send_file_data(new_client_socket)
new_client_socket.close()
#关闭套接字
tcp_server_socket.close()
if __name__ == "__main__":
main()
三、注意事项
不管是udp,还是tcp,数据发送发可绑定端口号,也可不绑定端口号,数据接收方必须绑定端口号。
问:我们的电脑可以同时打开两个QQ,显然QQ的端口号不是绑定的,怎么保证可以接收到别人发过来的消息?
答:A登陆的时候,腾讯服务器就收到A的ip和端口号,B登陆的时候,腾讯服务器同样也收到B的ip和端口号。当A发送消息给B时,消息先发送给腾讯服务器,腾讯服务器收到A的数据,再根据B的ip和端口号将数据转发给B。
|