socket
socket是进程间通信的一种方式,他可以实现不同主机间的进程通信,比如我们常用的QQ、微信等都是通过socket实现的。
一般使用的流程:
- 创建套接字
- 使用套接字
- 关闭套接字
import socket
socket.socket(AddressFamily, Type)
# AddressFamily是协议簇,包含(ipv4,ipv6)Type选择的是(TCP,UDP).
socket使用例子
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# ipv4, TCP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# ipv4, UDP
# 使用功能
# -----
# 关闭套接字
s.close()
udp
udp简单发送(客户端)
import socket
def main():
# 创建一个UDP套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 可以使用套接字收发数据
# udp_socket.sendto(b'hello', ('localhost',7890))
# 使用b无法录入汉字
# 从键盘中获取数据
send_data = input("请输入要发送的数据")
udp_socket.sendto(send_data.encode("utf-8"), ('localhost',7890))
# 关闭套接字
udp_socket.close()
if __name__ == "__main__":
main()
带有循环,退出功能的udp客户端
import socket
def main():
# 创建一个UDP套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
# 可以使用套接字收发数据
# 从键盘中获取数据
send_data = input("请输入要发送的数据")
# 如果输入的是exit,那么就退出
if send_data == "exit":
break
udp_socket.sendto(send_data.encode("utf-8"), ('localhost',7890))
# 关闭套接字
udp_socket.close()
if __name__ == "__main__":
main()
简单的UDP服务端
- 创建套接字
- 绑定端口
- 接收数据
- 关闭套接字
# 让自己的程序有一个固定的端口需要用bind绑定
# local_addr = ("", 7788) # 表示本机中的任何一个ip
import socket
def main():
# 1.创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2.绑定端口
localaddr = ('', 7890)
udp_socket.bind(localaddr)
# 3. 接收数据
while True:
recv_data = udp_socket.recvfrom(1024)
# recv_data 接收到的是一个元祖 (b'1', ('127.0.0.1', 60502))
# 接收到的数据,(ip,port)
recv_msg = recv_data[0] # 存储接收的数据
send_addr = recv_data[1] # 存储发送方的地址和端口
# 4. 打印收到的数据
print("%s:%s" %(str(send_addr), recv_msg.decode("utf-8")))
# 5.关闭套接字
udp_socket.close()
if __name__ == "__main__":
main()
证明udp是全双工
import socket
def main():
# 创建一个UDP套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 获取对方的IP/port
dest_ip = input("请输入对方的IP:")
dest_port = input("请输入对方的PORT:")
# 从键盘获取数据
send_data = input("请输入要发送的数据:")
# 使用套接字收发数据
udp_socket.sendto(send_data.encode("utf-8"),(dest_ip,dest_port))
# 打印接收的数据
recv_data = udp_socket.recvfrom(1024)
print(recv_data)
# 套接字可以同时收发(全双工)
# 单工:收音机。半双工:对讲机,全双工:电话
# 关闭套接字
udp_socket.close()
if __name__ == "__main__":
main()
udp聊天器
原始版
import socket
def main():
#创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#绑定信息
udp_socket.bind(("", 7890))
#循环处理事情
while True:
# 发送
dest_ip = input("请输入对方的ip:")
dest_port = int(input("请输入对方的port:"))
send_data = input("请输入要发送的消息:")
udp_socket.sendto(send_data.encode("utf-8"), (dest_ip, dest_port))
# 接收并显示
recv_data = udp_socket.recvfrom(1024)
print("%s:%s" % (str(recv_data[1], recv_data[0].decode("utf-8"))))
if __name__ == "__main__":
main()
简单UDP聊天器函数封装版
import socket
def send_msg(udp_socket):
# 发送 获取要发送的内容
dest_ip = input("ip:")
dest_port = int(input("port:"))
send_data = input("发送的消息:")
udp_socket.sendto(send_data.encode("utf-8"), (dest_ip, dest_port))
def recv_msg(udp_socket):
# 接收并显示
recv_data = udp_socket.recvfrom(1024)
print("%s:%s" %(str(recv_data[1]), recv_data[0].decode("utf-8")) )
def main():
# 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定信息
udp_socket.bind(("", 7755))
# 循环来 处理事情
while True:
print("----xxx聊天器----")
print('1 send')
print('2 receive')
print('0 exit')
op= input("请输入功能选项")
if op == '1':
send_msg(udp_socket)
elif op == '2':
recv_msg(udp_socket)
elif op == '0':
break
else:
print('wrong')
if __name__ == "__main__":
main()
tcp
udp在通信过程中不需要建立相关的连接,只要发送数据即可,类似于写信。
tcp在通信过程中有三个步骤:1.创建连接2.数据传输3.终止连接
tcp客户端
- 创建套接字
- 连接服务器
- 接收数据
- 关闭套接字
# tcp_client
import socket
def main():
# 1.创建套接字
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()
tcp服务端
- 创建socket套接字
- bind绑定ip和port
- listen使套接字改变为可以被动连接
- accept等待客户端的连接
- recv/send接收发送数据
# tcp服务端
import socket
def main():
# 创建套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定
tcp_server_socket.bind(("", 7890))
# 变为监听套接字,监听套接字负责等待有新的客户端进行连接
tcp_server_socket.listen(128)
print('----listen----')
new_client_socket, client_addr = tcp_server_socket.accept()
# accept产生的新的套接字用来为客户端服务
print('----break----')
print(client_addr)
# 接收客户端发送过来的请求
recv_data = new_client_socket.recv(1024)
print(recv_data)
#关闭套接字
new_client_socket.close()
tcp_server_socket.close()
if __name__ == "__main__":
main()
tcp服务器重复接待来访新客户
# tcp服务端
import socket
def main():
# 创建套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定
tcp_server_socket.bind(("", 7890))
# 变为监听套接字,监听套接字负责等待有新的客户端进行连接
tcp_server_socket.listen(128)
while True:
print('等待一个新客户端的到来')
new_client_socket, client_addr = tcp_server_socket.accept()
# accept产生的新的套接字用来为客户端服务
print('一个新的客户端已经到来%s' % str(client_addr))
print(client_addr)
# 接收客户端发送过来的请求
recv_data = new_client_socket.recv(1024)
# recv和recvfrom的区别就在于一个有客户的身份和信息,一个只有信息
print('客户端发来的请求是:%s' % recv_data.decode("utf-8"))
# 关闭套接字
# 关闭accept返回的套接字意味着不会为这个客户端服务
new_client_socket.close()
print("已经为客户服务完毕")
# 如果将监听套接字关闭了,那么会导致不能再次等待新客户端的到来,即xxx.accept失败
tcp_server_socket.close()
if __name__ == "__main__":
main()
文件下载器
client
# 文件下载-client
import socket
def main():
# 创建套接字
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取服务器的ip port
dest_ip = input('请输入下载器的IP:')
dest_port = int(input('请输入下载器的port:'))
# 连接服务器
tcp_socket.connect((dest_ip, dest_port))
# 获取下载的文件名字
download_file_name = input("请输入要下载的文件名字:")
# 将文件名字发送到服务器
tcp_socket.send(download_file_name.encode("utf-8"))
# 接收文件中的数据
recv_data = tcp_socket.recv(1024)
# 保存数据到一个文件
if recv_data:
with open('[new]'+download_file_name, 'wb') as f:
f.write(recv_data)
# 关闭套接字
tcp_socket.close()
if __name__ == "__main__":
main()
server
# 文件下载-server
import socket
def main():
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.bind(('',7890))
tcp_server_socket.listen(128)
new_client_socket, client_addr = tcp_server_socket.accept()
file_name = new_client_socket.recv(1024).decode("utf-8")
print("客户端%s下载的文件是%s" % (str(client_addr), file_name))
new_client_socket.send("hhaha".encode("utf-8"))
new_client_socket.close()
tcp_server_socket.close()
if __name__ == "__main__":
main()
server2
# 文件下载-server
import socket
def send_file_2_client(new_client_socket, client_addr):
# 接收客户端需要下载的文件名
file_name = new_client_socket.recv(1024).decode("utf-8")
print("客户端%s下载的文件是%s" % (str(client_addr), file_name))
file_connet = None
# 打开这个文件,读取数据
try:
f = open(file_name, 'rb')
file_connet = f.read()
f.close()
except Exception as ret:
print("没有要下载的文件%s" % file_name)
if file_connet:
new_client_socket.send(file_connet)
# 发送给客户端
def main():
# 创建套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定信息
tcp_server_socket.bind(('',7890))
# 监听
tcp_server_socket.listen(128)
while True:
# 等待客户链接
new_client_socket, client_addr = tcp_server_socket.accept()
send_file_2_client(new_client_socket, client_addr)
# 关闭套接字
new_client_socket.close()
tcp_server_socket.close()
if __name__ == "__main__":
main()