目录
一、UDP编程
二、TFTP文件下载器
三、TCP编程
一、UDP编程
UDP传输方式类似于发送短信,使用这种方式进行网络通讯时,不需要建立专门的虚拟连接,传输也不是很可靠,如果发送失败则客户端无法获得,因此大量的非核心数据可以通过UDP方式进行传递
1.数据的接收与发送
'''
from socket import socket,AF_INET,SOCK_DGRAM
#创建套接字
udp_socket=socket(AF_INET,SOCK_DGRAM)
#创建接收信息的地址
add=('112.32.173.157',8080)
#键盘接收发送的消息
data=input('输入要发送的信息')
#调用sendto方法发送信息
udp_socket.sendto(data.encode('gb2312'),add)
#关闭套接字
udp_socket.close()
'''
from socket import *
#创建UDP套接字
udp_socket=socket(AF_INET,SOCK_DGRAM)
#绑定一个端口
udp_socket.bind(('',8989))
add=('112.32.173.157',8080)
data=input('请输入要发送的信息')
#发送数据
udp_socket.sendto(data.encode('gb2312'),add)
recev_data=udp_socket.recvfrom(1024) #本次接收最大字节数为1024
print('接收到的信息是:%s'%(recev_data[1],recev_data[0].decode('gb2312')))
#关闭套接字
udp_socket.close()
?2.UDP使用多线程实现聊天
#导入模块
from socket import *
from threading import Thread
#创建UDP套接字对象
udp_socket=socket(AF_INET,SOCK_DGRAM)
#绑定本机与端口
udp_socket.bind(('', 8889)) #单引号代表本机
#接收
def recv_fun():
while True:
recv_data=udp_socket.recvfrom(1024)
print('>>%s:%s' % (recv_data[1], recv_data[0].decode('gb2312')))
#decode:字节转换成字符串
#发送
def send_fun():
while True:
add=('112.32.173.157', 8080)
data=input('<<:')
udp_socket.sendto(data.encode('gb2312'), add)
if __name__ == '__main__':
# 创建两个线程
t1=Thread(target=send_fun)
t2=Thread(target=recv_fun)
t1.start()
t2.start()
t1.join()
t2.join()
二、TFTP文件下载器
利用struck模块相关方法完成下载:
函数 | 描述 | pack(fmt, v1, v2..) | 按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流) | unpack(fmt, string) | 按照给定的格式(fmt)解析字节流string,返回解析出来的元组 | calcsize(fmt) | 计算给定的格式(fmt)占用多少字节的内存 |
#导入模块
import struct
from socket import *
filename='cat.png'
server_ip='112.32.173.157' #本地ip
#封装读请求
send_data=struct.pack('!H%dsb5sb' % len(filename), 1, filename.encode(), 0, 'octet'.encode(), 0)
#创建udp_socket套接字
udp_socket=socket(AF_INET, SOCK_DGRAM)
#将数据发送,读写端口默认为69
udp_socket.sendto(send_data, (server_ip, 69))
#在本地创建一个文件
f=open((filename,'ab')) #a表示追加模式,b表示二进制
while True:
recv_data=udp_socket.recvfrom(1024)
print(recv_data)
#获取操作码及数据块编号
caozuoma,ack_num=struct.unpack('!HH', recv_data[0][:4])
#判断操作码是否是5 如果是5,则是错误信息
if caozuoma == 5:
print('文件不存在')
break
#将接收到的数据写入到文件中
f.write(recv_data[0][4:])
if len(recv_data[0]) < 516: #表示读取完毕
break
#发送确认包
ack_data=struct.pack('!HH',4,ack_num)
#获取服务器发送数据的随机端口
rand_port=recv_data[1][1]
udp_socket.sendto(ack_data,(server_ip,rand_port))
三、TCP编程
TCP方式就类似于拨打电话,使用该种方式进行网络通讯时,需要建立专门的虚拟连接,然后进行可靠的数据传输,如果数据发送失败,则客户端会自动重发该数据,因此重要的数据一般使用TCP方式进行数据传输
1.数据的发送与接收
'''
#服务器端
from socket import *
#创建服务器端套接字
server_socket=socket(AF_INET,SOCK_STREAM)
#绑定端口
server_socket.bind(('',8888))
#监听是否有数据发送过来
server_socket.listen()
#接收客户端连接
client_socket,client_info=server_socket.accept()
#接收客户端发送的消息
recv_data=client_socket.recv(1024)
print("接收到%s的消息%s"%(client_info,recv_data.decode('gd2312')))
#关闭连接
client_socket.close()
server_socket.close()
'''
#双向通信,服务器端
from socket import *
#创建服务器端套接字
server_socket=socket(AF_INET,SOCK_STREAM)
#绑定端口
server_socket.bind(('',8888))
#监听是否有数据发送过来
server_socket.listen()
#等待客户端连接
client_socket,client_info=server_socket.accept()
while True:
# 接收客户端发送的消息
recv_data = client_socket.recv(1024)
print('客户端:',recv_data.decode('utf-8'))
#发送消息
msg=input('>>:')
client_socket.send(msg.encode('utf-8'))
#客户端
from socket import *
#创建客户器端套接字
client_socket=socket(AF_INET,SOCK_STREAM)
#调用方法与服务器建立连接
client_socket.connect(('112.32.173.157',8888))
while True:
#客户端发送信息
msg=input('>>:')
client_socket.send(msg.encode('utf-8'))
#客户端接收消息
recv_data=client_socket.recv(1024)
print("服务器端说:",recv_data.decode('utf-8'))
client_socket.close()
server_socket.close()
2.使用多线程进行通信
#服务器端
from socket import *
from threading import Thread
sockets=[]
def main():
#创建服务器端套接字
server_socket=socket(AF_INET,SOCK_STREAM)
#绑定端口
server_socket.bind(('',8888))
#监听是否有数据发送过来
server_socket.listen()
#接收客户端请求
while True:
client_socket,client_info=server_socket.accept()
sockets.append(client_socket)
#开启线程处理当前客户端的请求
t=Thread(target=readMsg)
t.start()
def readMsg(client_socket):
#读取客户端的消息
while True:
recv_data=clien_socket.recv(1024)
#将消息发送给所有在线客户端
#遍历所有在线客户端列表
for socket in sockets:
socket.send(recv_data)
if __name__=="__main__":
main()
#客户端
from socket import *
from threading import Thread
def readMsg(client_socket):
while True:
recv_data=client_socket.recv(1024)
print("收到:",recv_data.decode('utf_8'))
def writeMsg(client_socket):
while True:
msg=input(">>:")
client_socket.send(msg.encode('utf_8'))
#创建客户端套接字
client_socket=socket(AF_INET,SOCK_STREAM)
#调用方法连接服务器
client_socket.connect(('112.32.173.157',8888))
#开启一个线程处理客户端的读取消息
t=Thread(target=readMsg,args=(client_socket,))
t.start()
#开启一个线程处理客户端的发送消息
t=Thread(target=writeMsg,args=(client_socket,))
t.start()
|