Python 网络编程(Socket)

Python 网络编程(Socket)


一、Socket 套接字

1、Socket 编程

  • socket本质是编程接口(API),对TCP/IP的封装,提供可供程序员做网络开发所用的接口。Socket 编程是应用进程间通信的抽象机制。
  • 应用编程接口API:应用进程的控制权和操作系统的控制权进行转换的一个系统调用接口
  • Socket 的意思为“插座”。是 BSD UNIX 的进程通信机制,通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原义那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,提供不同的服务。 客户软件将插头插到不同编号的插座,就可以得到相应的服务。

2、Socket

Socket 标识:

  • 不同主机间 Socket 连接的标识:IP地址+端口号
  • 操作系统/进程管理套接字的标识:套接字描述符(socket descriptor),小整数

Socket 创建:

  • 当应用进程创建套接字时,操作系统分配一个数据结构存储该套接字相关信息,返回套接字描述符
  • 每个进程有一个 Socket 描述符表
  • 如果多个进程共享一个套接字,关闭套接字时引用计数减1,减至0才关闭
  • 如果进程中的一个线程将一个套接字关闭,该套接字直接关闭,该进程中的其他线程也将不能访问该套接字

二、TCP

1、客户端

访问网站: HTTP 协议

# 导入socket库
import socket

# 创建一个socket,AF_INET 表示采用 IPv4 网络协议,SOCK_STREAM 表示 TCP 连接
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 建立连接,需指明端口号,web 服务端口默认为 80
s.connect(('www.baidu.com', 80))

# 发送数据
s.send(b'GET / HTTP/1.1\r\nHost:www.baidu.com\r\nConnection:close\r\n\r\n')

# 接收数据
buffer = []
while True:
    # 每次最多接收1k字节
    d = s.recv(1024)
    if d:
        buffer.append(d)
    else:
        break
data = b''.join(buffer)

# 关闭连接
s.close()

# 解析服务器响应数据
header, html = data.split(b'\r\n\r\n', 1)
print(header.decode('utf-8'))
# 把接收的数据写入文件
with open('baidu.html', 'wb') as f:
    f.write(html)

自定义连接:

# 导入socket库
import socket

# 创建一个socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 建立连接
s.connect(('127.0.0.1', 5000))

# 接收欢迎消息
print(s.recv(1024).decode('utf-8'))
for data in [b'Python', b'C++', b'AI']:
    # 发送数据
    s.send(data)
    # 接受数据
    print(s.recv(1024).decode('utf-8'))

# 发送结束连接信号
s.send(b'exit')

# 关闭连接
s.close()

2、服务器

# 导入 socket 库,threading 库
import socket
import threading
import time

# 处理请求函数
def tcp_link(sock, addr):
    print('Accept new connection from %s:%s...' % addr)
    sock.send(b'Welcome!')
    # 接收、发送数据
    while True:
        data = sock.recv(1024)
        time.sleep(1)
        if not data or data.decode('utf-8') == 'exit':
            break
        sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))

    # 关闭连接
    sock.close()
    print('Connection from %s:%s closed.' % addr)

# 创建一个socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定端口
s.bind(('127.0.0.1', 5000))

# 监听端口,5表示最多同时监听5个
s.listen(5)
print('Waiting for connection...')

# 等待连接,处理连接
while True:
    # 接受一个新连接
    sock, addr = s.accept()
    # 创建新线程来处理TCP连接
    t = threading.Thread(target=tcp_link, args=(sock, addr))
    t.start()

三、UDP

1、客户端

# 导入socket库:
import socket

# 创建一个socket,SOCK_DGRAM 表示 UDP 连接
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 数据发送与接收
for data in [b'Python', b'C++', b'AI']:
    # 发送数据:
    s.sendto(data, ('127.0.0.1', 5000))
    # 接收数据:
    print(s.recv(1024).decode('utf-8'))

# 关闭连接
s.close()

2、服务器

# 导入socket库:
import socket
import threading

# 处理请求函数
def udp_link(data, addr):
    print('Received from %s:%s.' % addr)
    s.sendto(b'Hello, %s!' % data, addr)

# 创建一个socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 绑定端口:
s.bind(('127.0.0.1', 5000))
print('Bind UDP on 5000...')

# 等待接收数据并处理
while True:
    # 接收数据:
    data, addr = s.recvfrom(1024)
    t = threading.Thread(target=udp_link, args=(data, addr))
    t.start()

GOOD LUCK!


### Python 中使用 `socket` 模块进行网络编程 #### 基本概念 在网络编程中,`Socket` 是一种通信机制,允许程序之间通过网络交换数据。在 Python 中,`socket` 模块提供了一种方式来创建和管理这些套接字对象[^1]。 #### 创建套接字 为了建立连接并传输数据,在 Python 中可以通过调用 `socket.socket()` 函数来实例化一个新的套接字对象。此函数接受几个参数以指定协议族(如 AF_INET 表示 IPv4)、套接字类型(SOCK_STREAM 或 SOCK_DGRAM),以及其他选项[^3]。 ```python import socket # 创建TCP/IP套接字 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ``` #### 绑定地址与监听请求 对于服务器端应用来说,通常会绑定到特定 IP 地址及端口号,并进入监听状态等待来自客户端的连接请求: ```python server_address = ('localhost', 10000) print('启动服务器...') try: sock.bind(server_address) # 将套接字绑定到本地地址 except Exception as e: print(f'无法绑定 {e}') sock.listen(5) # 开始监听传入连接;最大队列长度为5 ``` #### 接受新连接 当有新的客户尝试连接时,服务器可以调用 accept 方法接收该连接,并返回一个代表已建立连接的新套接字以及对方的信息: ```python connection, client_address = sock.accept() with connection: print('收到连接:', client_address) while True: data = connection.recv(16) if not data: break print('收到来自{}的数据: {!r}'.format(client_address, data)) connection.sendall(data.upper()) ``` 上述代码展示了如何处理简单的回显服务——即把从客户端接收到的消息转换成大写形式再发回去[^2]。 #### 客户端发送消息给服务器 而作为客户端,则需主动发起连接至目标主机上的某个开放端口,并向其发送信息或者读取响应内容: ```python messages = [ '这是第一条消息', '这是第二条消息' ] for message in messages: try: sent = sock.sendto(message.encode(), server_address) amount_received = 0 amount_expected = len(message) while amount_received < amount_expected: data, _ = sock.recvfrom(16) amount_received += len(data) print('收到回复:', data.decode()) finally: print('关闭套接字') sock.close() ``` 这段脚本演示了怎样构建一个基本的 UDP 客户端,它能够依次发送多条短语给远程服务器,并打印出所获得的所有回应。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值