Socket is an external programming interface provided by TCP/IP , which is the encapsulation and application of TCP/IP.
Socket is called "socket" and is used to describe IP addresses and ports . It is a communication and chain handle, which can realize communication between different virtual machines or different computers. Two programs on the network exchange data through a two-way communication connection, and the application program sends a request to the network or responds to a network request through a "socket".
The main purpose of the Socket module is to help establish a channel of information between two programs on the network. Two basic Socket modules are provided in Python: server-side Socket and client-side Socket .
When a server Socket is created, the Socket will wait for a connection on a port of the machine , and the client Socket will access this port. After the two complete the connection, they can interact.
Write a simple server and client using Socket
Multithreaded server program:
# -*- coding: UTF-8 -*-
import socket # 导入 socket 模块
import threading
# 处理客户端的请求操作
def handle_client_request(service_client_socket, ip_port):
# 循环接收客户端发送的数据
while True:
# 接收客户端发送的数据
recv_data = service_client_socket.recv(1024)
# 容器类型判断是否有数据可以直接使用if语句进行判断,如果容器类型里面有数据表示条件成立,否则条件失败
# 容器类型: 列表、字典、元组、字符串、set、range、二进制数据
if recv_data:
message = recv_data.decode()
print(message)
print(ip_port)
# 回复
service_client_socket.send("已接收...".encode())
else:
print("客户端下线了:", ip_port)
print()
break
# 终止和客户端进行通信
service_client_socket.close()
if __name__ == '__main__':
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口号复用,让程序退出端口号立即释放
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", 9090))
# 设置监听, listen后的套接字是被动套接字,只负责接收客户端的连接请求
tcp_server_socket.listen(128)
# 循环等待接收客户端的连接请求
while True:
# 等待接收客户端的连接请求
service_client_socket, ip_port = tcp_server_socket.accept()
print("客户端连接成功:", ip_port)
# 当客户端和服务端建立连接成功以后,需要创建一个子线程,不同子线程负责接收不同客户端的消息
sub_thread = threading.Thread(target=handle_client_request, args=(service_client_socket, ip_port))
# 设置守护主线程
sub_thread.setDaemon(True)
# 启动子线程
sub_thread.start()
# tcp服务端套接字可以不需要关闭,因为服务端程序需要一直运行
# tcp_server_socket.close()
Client program:
# -*- coding: UTF-8 -*-
import socket # 导入 socket 模块
if __name__ == '__main__':
sk = socket.socket() # 创建 socket 对象
host = socket.gethostname() # 获取本地主机名
port = 9090 # 设置端口号
sk.connect((host, port))
message = "connect······"
sk.sendall(message.encode())
print(sk.recv(1024).decode())
i = 0
while True:
try:
message = input(">>>")
sk.send(message.encode())
print(sk.recv(1024).decode())
except KeyboardInterrupt:
break
sk.close()
operation result:
Socket instantiation
Format:
sk = socket.socket(family,type[,protocal])
family : address family, commonly used address families are AF_INET, AF_INET6, AF_LOCAL (or AF_UNIX, UNIX domain Socket), AF_ROUTE, etc. The default is AF_INET, usually you can use the default.
type : Socket type
SOCK_STREAM, TCP type (default)
SOCK_DGRAM, UDP type
SOCK_RAM, original type, allowing direct access to underlying protocols such as IP or ICMP, basically not used.
protocol : optional, the protocol used, usually assigned the value "0", automatically selected by the system.
Socket common functions
- bind()
is called by the server Socket to bind the previously created Socket to the specified IP address and port.
sk.bind(("127.0.0.1",9090))
- listen() is used to enable the listening mode on the server
using TCP .
#服务端开启一个监听,最大连接数为5
sk.listen(128)
- accept() is used to receive connections on the server side
using TCP , generally in a blocking state. Accept the TCP connection and return (conn, adress), where conn is a new socket object that can be used to receive and send data, and address is the address of the connected client.
socket_new, port = sk.accept()
- connect() is used when the client
using TCP connects to the server
sk.connect(("127.0.0.1", 9090))
- send()
is used to send data when using TCP, and may not send all the specified content.
sk.send(string[,flag]) #返回值是发送字节数量
- sendall()
is used to send data when using TCP, and send TCP data completely .
# 发送一段字符到Socket
sk.sendall("Hello!".encode())
# 成功返回None,失败抛出异常
- recv()
is used to receive data using TCP.
sk.recv(bufsize[,flag])
# bufsize指定最多可以接收的数量
-
sendto() is used to send data when
using UDP -
recvfrom()
is dedicated to UDP , receives data, and returns the remote IP address and port -
close()
closes the Socket