socket简介
socket(简称 套接字)是进程之间通信的一种方式,与其他进程间通信的一个主要不同是:它能实现不同主机间的进程通信。
创建套接字
函数scocket.socket创建一个socket,该函数有两个参数:
1、AF_INET(用于internet进程间的通信) 或者 AF_UNIX(用于同一台机器进程间通信),工作中常用AF_INET
2、SOCKET_STREAM(流式套接字,主要用于TCP协议) 或者 SOCKET_DGRAM(数据报套接字,主要用于UDP)
import socket
# 1、创建TCP套接字
socket = socket.socket(socket.AF_INET, socket.SOCKET_STREAM)
# 2、使用套接字
# ......
# 3、使用完成后关闭套接字
socket.close()
socket套接字:UDP协议
1、创建套接字并使用UDP协议创建一个Client
import socket
# 创建udp套接字
udp_client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 指定一个ip地址 与 端口号;ip地址用于标识网络中的计算机,端口号可以理解用于标识该ip地址计算机中的应用程序,这里的ip地址是笔者电脑的ip
ip_port = ('192.168.0.104', 8000)
# 准备向指定的ip与端口发起通信
send_data = input("请输入要发送的信息:")
# 发送通信信息,sendto发送的数据是byte(字节)类型,需要使用encode将其转码,windows之间通常使用utf-8
udp_client.sendto(send_data.encode("utf-8"), ip_port)
# 使用完成后关闭
udp_client.close()
上述代码可以理解为一个客户端使用UDP协议向服务器发起通信
2、创建套接字并使用UDP协议创建一个Server
import socket
# 创建udp套接字
udp_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 指定一个ip地址 与 端口号;这里的ip可以不用填写,即本机ip(127.0.0.1)
ip_port = ('', 8000)
# 绑定ip与端口,禁止系统自动分配
udp_server.bind(ip_port)
# 等待客户端发起通信信息,此时处于堵塞状态,1024表示本次接收的最大字节数
recv_data = udp_server.recvfrom(1024)
# 打印接收的数据,接收的数据是一个元组,元组的第一个元素即是客户端发起通信的数据信息,第二个元素是一个元组(ip与端口)
print(recv_data[0].decode("utf-8"))
# 使用完成后关闭
udp_server.close()
可以看出client的代码与server的代码几乎一样,不同的是client的ip地址与端口指向的是服务器;server的ip地址与端口标识的是本机,并且使用了bind进行了ip与port的绑定。
(演示时两个程序在同一电脑上使用请使用同一ip地址;并且使用client率先向服务器发起通信)
socket套接字:TCP协议
1、创建套接字并使用TCP协议创建一个Client
import socket
# 创建TCP套接字
tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 指定一个ip地址 与 端口号
ip_port = ('192.168.0.104', 8000)
# 连接指定的ip与端口
tcp_client.connect(ip_port)
# 准备向指定的ip与端口的服务器发起请求
send_data = input("请输入要发送的信息:\n")
# 发送信息请求,encode编码,windows之间可以忽略不写
tcp_client.send(send_data.encode())
# 服务器返回的数据,并使用decode解码
server_recv_data = tcp_socket.recv(128).decode()
# 将返回的数据打印
print(server_recv_data)
# 关闭套接字
tcp_client.close()
2、创建套接字并使用TCP协议创建一个Server
import socket
# 创建tcp套接字
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 指定一个ip地址 与 端口号并进行绑定
ip_port = ('', 8000)
tcp_server.bind(ip_port)
# 使用 listen 将套接字变为可以被动连接,最多连接数128
tcp_server.listen(128)
# 等待客户端连接,返回值是一个元组,阻塞状态
client_socket, client_addr = tcp_socket.accept()
# 元组的第一个元素是请求该服务器的客户端的socket套接字对象,第二个元素是请求该服务器的客户端的ip与port
print("Client_addr:",client_addr)
# 接收客户端发送的请求,decode解码并打印
recv_data = client_socket.recv(1024).decode()
print("Client_data:",recv_data)
# 向客户端返回的 数据为:'Hello!'+请求该服务器的客户端的ip与port
send_data = "Hello!"+str(client_addr[0])+':'+str(client_addr[1])
# 返回数据
client_socket.send(send_data.encode())
# 关闭请求的客户端的套接字
client_socket.close()
# 使用完成后关闭
tcp_server.close()
TCP的socket套接字与UDP稍有不同,在同一机器上演示TCP协议时,需要注意ip与port,并且需要先运行tcp_server程序再运行tcp_client发送请求
总结
socket 的使用流程可以大致分为:
1、创建 tcp/udp 套接字对象
import socket
#--------------------TCP----------------------
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#--------------------UDP----------------------
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
2、指定 ip与port
ip_port = ('127.0.0.1', 8000)
如果是服务器,则需要进行 bind 绑定操作;
#--------------------TCP-server---------------------
tcp_server.bind(ip_port)
#--------------------UDP-server---------------------
udp_server.bind(ip_port)
如果是TCP协议服务端还需要使用 listen 将套接字变为被动连接状态,并且还需要使用 accept() 等待客户端连接
#--------------------TCP-server---------------------
tcp_server.listen(128)
client_socket, client_addr = tcp_socket.accept()
如果是TCP协议需要使用 connect 连接指定的服务器
#--------------------TCP-client---------------------
tcp_client.connect(ip_port)
3、客户端向服务端发送数据信息
#--------------------TCP-client---------------------
tcp_client.send(send_data.encode())
#--------------------UDP-client---------------------
udp_client.sendto(send_data.encode("utf-8"), ip_port)
4、服务器处理客户端发送过来的数据
#--------------------UDP-server---------------------
recv_data = udp_server.recvfrom(1024)
print(recv_data[0].decode("utf-8"))
#--------------------TCP-server---------------------
client_socket, client_addr = tcp_socket.accept()
print("Client_addr:",client_addr)
recv_data = client_socket.recv(1024).decode()
print("Client_data:",recv_data)
TCP协议进行返回数据操作
#--------------------TCP-sever---------------------
send_data = "Hello!"
client_socket.send(send_data.encode())
UDP一般不会进行返回数据操作
如果是 TCP_server 端在关闭socket套接字之前还需要关闭请求的客户端的套接字
#--------------------TCP-server---------------------
client_socket.close()
6、关闭 socket 套接字
#--------------------UDP----------------------
udp_client.close()
udp_server.closer()
#--------------------TCP----------------------
tcp_client.close()
tcp_server.close()