1、TCP链接
TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。所以在进行TCP链接时首先要开启服务器端口。
TCP服务端一般有几个步骤:
① sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 创建套接字,第一个参数为套接字家族AF_INET:基于网络的套接字家族;第二个参数SOCK_STREAM:基于TCP协议的通信类型。创建时不带参数默认创建基于TCP协议的网络链接。
② sk.bind(address) 绑定本机地址与端口号,address:元组,第一个元素为本机ip地址,第二个元素为端口号。
③ sk.listen() 开始监听TCP传入链接。
④ sock, addr = sk.accept() 接收成功链接的TCP并返回元组(sock, addr),元组第一个元素为新的套接字,负责与链接成功的客户端通信,元组第二个元素为地址,包含IP,与端口号,即 addr = (ip, port)
⑤ sock.recv(bufsize) bufsize 指定最大接收字节数,返回一个bytes对象,即字节数组。没有数据接收时线程在此堵塞
⑥ sock.send(bytes) 将bytes发送到tcp客户端,返回发送的字节数,接收和发送可以并发执行
⑦ sock.close() 将与客户端通信的套接字关闭,关闭后不能与该客户端进行通信
⑧ sk.close() 将服务端监听套接字关闭,关闭后将不能接收新的链接
TCP客户端一般有几个步骤:
① sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 创建套接字
② sk.connect(("127.0.0.1", 8899)) 链接客户端
③ sk.send(bytes) 将bytes发送到服务器,返回发送的字节数
④ msg = sk.recv(bufsize) 接收数据,接收和发送可以并发执行
⑤ sk.close() 关闭套接字
1 import socket
2
3
4 def fn(conn):
5 msg = conn.recv(1024).decode("utf-8")
6 print("服务端收到>>>", msg)
7 conn.send(msg.encode("utf-8"))
8 print("服务端发送消息到客户端>>>", msg)
9
10
11 if __name__ == "__main__":
12 sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
13 sk.bind(("127.0.0.1", 8899))
14 sk.listen()
15 while True:
16 conn, addr = sk.accept()
17 print("已连接服务器-->", addr)
18 fn(conn)
19 sk.close()
20
21
22 # 输出结果
23 已连接服务器--> ('127.0.0.1', 55921)
24 服务端收到>>> hhh
25 服务端发送消息到客户端>>> hhh
1 import socket
2
3 sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4 sk.connect(("127.0.0.1", 8899))
5 msg = input()
6 sk.send(msg.encode("utf-8"))
7 print("客户端发送的内容>>>", msg)
8 msg = sk.recv(1024).decode("utf-8")
9 print("客户端收到>>>", msg)
10 sk.close()
11
12
13 # 输出结果
14 hhh
15 客户端发送的内容>>> hhh
16 客户端收到>>> hhh
1 import socket
2 from threading import Thread
3
4
5 def fn(conn):
6 msg = conn.recv(1024).decode("utf-8")
7 print("服务端收到>>>", msg)
8 conn.send(msg.encode("utf-8"))
9 print("服务端发送消息到客户端>>>", msg)
10
11
12 if __name__ == "__main__":
13 sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
14 sk.bind(("127.0.0.1", 8899))
15 sk.listen()
16 while True:
17 conn, addr = sk.accept()
18 print("已连接服务器-->", addr)
19 t = Thread(target=fn, args=(conn,))
20 t.start()
21 sk.close()
22
23
24 # 输出结果已连接服务器--> ('127.0.0.1', 55938)
25 已连接服务器--> ('127.0.0.1', 55939)
26 已连接服务器--> ('127.0.0.1', 55940)
27 服务端收到>>> 111
28 服务端发送消息到客户端>>> 111
29 服务端收到>>> 222
30 服务端发送消息到客户端>>> 222
31 服务端收到>>> 333
32 服务端发送消息到客户端>>> 333
2、UDP连接
udp服务端连接步骤:
① sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 创建套接字
② sk.bind(addr) 绑定指定端口和地址,服务端必须绑定,不然客户端无法知道服务端的端口号。客户端可不进行绑定程序运行时随机绑定一个端口号
③ recv_msg, recv_addr = sk.recvfrom(bufsize) 接收数据,没有数据接收时线程在此堵塞
④ sk.sendto(bytes, recv_addr) 发送数据,udp每一次发送数据都需要指定地址,发送与接收可以并发执行
⑤ sk.close() 关闭socket
udp客户端连接步骤:
① sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 创建套接字
② sk.sendto(bytes, recv_addr) 发送数据,返回发送的字节数,udp每一次发送数据都需要指定地址,发送与接收可以并发执行
③ recv_msg, recv_addr = sk.recvfrom(bufsize) 接收数据,没有数据接收时线程在此堵塞
④ sk.close() 关闭socket
1 import socket
2
3 print("-----server------")
4
5 addr = ("127.0.0.1", 8899)
6 sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
7 sk.bind(addr)
8
9 recv_msg, recv_addr = sk.recvfrom(1024)
10 print("服务端收到>>>", recv_msg.decode("utf-8"), recv_addr)
11 msg = "AAA"
12 sk.sendto(msg.encode("utf-8"), recv_addr)
13 print("服务端发送>>>", msg)
14
15 sk.close()
16
17
18 # 输出结果
19 -----server------
20 服务端收到>>> BBB ('127.0.0.1', 55802)
21 服务端发送>>> AAA
1 import socket
2
3 print("-----client------")
4
5 server_addr = ("127.0.0.1", 8899)
6 sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
7
8 msg = "BBB"
9 sk.sendto(msg.encode("utf-8"), server_addr)
10 print("客户端发送>>>", msg)
11 recv_msg, recv_addr = sk.recvfrom(1024)
12
13 print("客户端发送>>>", recv_msg.decode("utf-8"), recv_addr)
14
15 sk.close()
16
17
18 # 输出结果
19 -----client------
20 客户端发送>>> BBB
21 客户端发送>>> AAA ('127.0.0.1', 8899)