网络编程

客户端/服务器架构

服务端提供服务

客户端请求服务

套接字:通信端点

套接字是计算机网络数据结构,它体现了“通信端点”的概念。

在任何类型的通信开始之前,网络应用程序必须创建套接字。

可以将它们比作电话插孔,没有它将无法进行通信。

Python 中的网络编程

socket()模块函数

要创建套接字,必须使用 socket.socket()函数,它一般的语法如下。

1
socket(socket_family, socket_type, protocol=0)

socket_family 是 AF_UNIX 或 AF_INET

socket_type 是 SOCK_STREAM或 SOCK_DGRAM

protocol 通常省略,默认为 0

使用以下方式创建TCP/UDP套接字

1
2
3
4
5
from socket import *

TCPSock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

UDPSpck=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

套接字对象(内置)方法

常见的套接字对象方法和属性

名 称 描 述
服务器套接字方法
s.bind() 将地址(主机名、端口号对)绑定到套接字上
s.listen() 设置并启动 TCP 监听器
s.accept() 被动接受 TCP 客户端连接,一直等待直到连接到达(阻塞)
客户端套接字方法
s.connect() 主动发起 TCP 服务器连接
s.connect_ex() connect()的扩展版本,此时会以错误码的形式返回问题,而不是抛出一个异常
普通的套接字方法
s.recv() 接收 TCP 消息
s.recv_into()① 接收 TCP 消息到指定的缓冲区

(续表)

名 字 描 述
s.send() 发送 TCP 消息
s.sendall() 完整地发送 TCP 消息
s.recvfrom() 接收 UDP 消息
s.recvfrom_into()① 接收 UDP 消息到指定的缓冲区
s.sendto() 发送 UDP 消息
s.getpeername() 连接到套接字( TCP)的远程地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回给定套接字选项的值
s.setsockopt() 设置给定套接字选项的值
s.shutdown() 关闭连接
s.close() 关闭套接字
s.detach() 在未关闭文件描述符的情况下关闭套接字,返回文件描述符
s.ioctl() 控制套接字的模式(仅支持 Windows)
面向阻塞的套接字方法
s.setblocking() 设置套接字的阻塞或非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 获取阻塞套接字操作的超时时间
面向文件的套接字方法
s.fileno() 套接字的文件描述符
s.makefile() 创建与套接字关联的文件对象
数据属性
s.family 套接字家族
s.type 套接字类型
s.proto 套接字协议

创建TCP服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/env/python3
#-*- coding:utf8 -*-
import socket
import sys

Server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建服务端套接字

HOST = '127.0.0.1'
PORT = 9999
ADDRS=(HOST,PORT)
Server.bind(ADDRS) #绑定IP,Port
Server.listen(2) #最大连接数
print("正在监听:%s:%d"%(HOST,PORT))

while True: #服务器无限循环
Client, addr = Server.accept() #接受客户端连接
print("连接来自:%s" % str(addr)) #打印客户端连接IP
msg = 'Wlecome to here!\n'
#send()和recv()的数据格式都是bytes。
# (str和bytes的相互转化,用encode()和decode(),或者用bytes()和str())
while True:
Client.send(msg.encode("utf-8")) # 发送欢迎标语
msg = Client.recv(1024) #接受并输出信息
print("接收到客户端数据:%s" % msg.decode("utf-8"))
msg=input('输入>') # 输入信息
Client.close()
Server.close()

创建TCP客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env/python3
#-*- coding:utf8 -*-
import socket

Client= socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 创建客户端套接字

HOST = '127.0.0.1'
PORT = 9999
ADDRS=(HOST,PORT)
Client.connect(ADDRS) # 连接服务器
while True:
msg = Client.recv(1024)
print("接受到服务端数据:%s" % msg.decode("utf-8"))
msg = input('输入>')
Client.send(msg.encode("utf-8"))
Client.close()

运行结果

创建UDP服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python3
#-*- coding:utf8 -*-
import socket

HOST='127.0.0.1'
PORT=9999
ADDR=(HOST,PORT)
BUFSIZE=1024

Server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
Server.bind(ADDR)
print("正在监听 %s:%d" % (HOST,PORT) )
while True:
msg,ADDR=Server.recvfrom(BUFSIZE)
print("接收到来自客户端的数据:%s" % msg.decode("utf-8"))
msg=input('输入>')
Server.sendto(msg.encode("utf-8"),ADDR)
Server.close()

创建UDP客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python3
#-*- coding:utf8 -*-

import socket

HOST='127.0.0.1'
PORT=9999
ADDR=(HOST,PORT)
BUFSIZE=1024

Client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
msg = input('输入>')
Client.sendto(msg.encode("utf-8"),ADDR)
msg,ADDR=Client.recvfrom(BUFSIZE)
print("接收到服务端的数据:%s" % msg.decode("utf-8"))
Client.close()

运行结果