Python的网络编程[0] -> socket[2] -> 利用 socket 建立 TCP/UDP 通信
Socket
目录
socket的TCP/IP通信连接主要包括两个部分,服务端与客户端
1.1 Socket server服务端建立
服务端建立步骤主要有:
- 初始化IP地址和端口号;
- 生成socket实例,TCP/IP通信选择AF_INET(IPV4),SOCK_STREAM(流套接字类型,数据像字符流一样通过);
- bind()函数绑定IP和端口,listen()函数设置最大监听数量;
- accept()函数接收client的连接,对于连接的client返回2个参数cs,addr,cs为一个新生成的socket类,用于与连接的client进行通讯,addr包含IP和端口号信息;
- 基于生成的cs与client进行通讯。
1 # server
2
3 import socket
4 # set IP and Port
5 address = ('127.0.0.1', 31500)
6 # choose IPV4, stream type
7 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
8 # bind address and ip
9 s.bind(address)
10 # allow max five connection
11 s.listen(5)
12
13 while True:
14 # wait client's request, cs is a new socket object and server use it to communicate with client
15 cs, address = s.accept()
16 print('got connected from', address)
17 # send message to client
18 cs.send(b'hello I am server, welcome')
19 # receive message from client and decode
20 re = cs.recv(1024).decode('utf-8')
21 print(re)
22 cs.close()
1.2 Socket client客户端建立
客户端建立步骤主要有:
- 初始化IP地址和端口号;
- 生成socket实例,TCP/IP通信选择AF_INET(IPV4),SOCK_STREAM(流套接字类型,数据像字符流一样通过);
- connect()函数进行IP和端口连接(对应的服务端会利用accept()函数生成一个通信实例进行两者相互之间的通信);
- 利用send()函数和recv()函数开始通信。
1 # client
2
3 import socket
4
5 address = ('127.0.0.1', 31500)
6 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
7 # connect address to correct ip and port
8 s.connect(address)
9 s.send(b'hello, I am client')
10 data = s.recv(1024).decode('utf-8')
11 print('the data received is', data)
12
13 s.close()
socket的UDP通信连接主要包括两个部分,服务端与客户端
2.1 Socket server服务器建立
服务器建立步骤主要有:
- 设置端口号,ip地址可以为空字符(‘’),即表示接受任何地址来的数据报;
- 生成socket实例,UDP通信选择AF_INET(IPV4),SOCK_DGRAM(数据报套接字类型,数据以数据报datagrams通过);
- bind()函数绑定IP和端口;
- 利用recvfrom()函数进行数据接收,获得参数msg,addr,这两个参数分别为信息和客户端的地址,可根据收到的addr进行通信回复。
1 import socket
2 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
3 sock.bind(('', 5656))
4 print('server ready')
5 while True:
6 msg, addr = sock.recvfrom(1024)
7 print(msg, addr)
8 sock.sendto(b'hi, this is server', addr)
2.2 Socket client客户端建立
客户端建立步骤主要有:
- 生成socket实例,UDP通信选择AF_INET(IPV4),SOCK_STREAM(数据报套接字类型,数据以数据报datagrams通过);
- 无需连接直接利用sendto函数向目标ip和端口发送数据;
- 利用recvfrom()函数接收服务端的数据。
1 import socket
2 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
3 sock.sendto(b'hi, this is client.', ('localhost', 5656))
4 data, msg = sock.recvfrom(1024)
5 print(data, msg)
3.1 Socket broadcast server服务端建立
服务端建立步骤主要有:
- 生成UDP的socket实例;
- 利用setsockopt设置socket的broadcast模式为True,地址复用(多个套接字可以同时连接一个端口上);
- bind()函数绑定IP和端口;
- 利用recvfrom()函数进行数据接收,获得参数msg,addr,这两个参数分别为信息和客户端的地址,可根据收到的addr进行通信回复。
1 import socket
2 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
3 sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True)
4 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
5 sock.bind(('', 5656))
6 print('server ready')
7 while True:
8 msg, addr = sock.recvfrom(1024)
9 print(msg, addr)
10 sock.sendto(b'hi, this is server', addr)
3.2 Socket broadcast client客户端建立
客户端建立步骤主要有:
- 生成UDP的socket实例;
- 利用setsockopt设置socket的broadcast模式为True,地址复用(多个套接字可以同时连接一个端口上);
- 无需连接直接利用sendto函数以广播形式向<’broadcast’>和端口发送数据;
- 利用recvfrom()函数接收服务端的数据。
1 import socket
2 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
3 sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True)
4 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
5 for i in range(5):
6 sock.sendto(b'hi, this is client.', ('<broadcast>', 5656))
7 data, msg = sock.recvfrom(1024)
8 print(data, msg)
4.1 Socket thread server多线程服务端建立
多线程服务器的服务器建立与前面相同,唯一不同之处在于accept函数返回新的通信socket后调用线程模块启动一个新的子线程进行通信。
此处补充建立了一个单线程的服务端,最终结果可以看出单线程的服务端需等待程序再次循环至accept处才能继续下一个客户端的通信。
1 from socket import *
2 from threading import Thread
3
4 class Service():
5 def __init__(self):
6 #self.ip = '192.168.121.100'
7 #self.port = 2049
8 self.ip = '127.0.0.1'
9 self.port = 31500
10 self.addr = (self.ip, self.port)
11 self.serv = socket(AF_INET, SOCK_STREAM)
12 self.serv.bind(self.addr)
13
14 self.serv.listen(5)
15
16 def run(self):
17 while True:
18 newServ, addr = self.serv.accept()
19 Thread(target=self.chat, args=(newServ, )).start()
20
21 def chat(self, newServ):
22 i = 1
23 while i <= 10:
24 newServ.send('get data'.encode('utf-8'))
25 ra = newServ.recv(1024).decode('utf-8')
26 print(ra)
27 #newServ.close()
28 print('next')
29 i += 1
30
31 class Servicex(Service):
32 def __init__(self):
33 Service.__init__(self)
34
35 def run(self):
36 while True:
37 newServ, addr = self.serv.accept()
38 self.chat(newServ)
39
40 #serv = Service()
41 #serv.run()
42
43 serv = Servicex()
44 serv.run()
4.2 Socket thread client多线程客户端建立
多线程服务器的客户端建立与前面相同,不同之处在于生成了两个socket的实例,并用线程模块同时调用运行这两个socket通信实例进行通信。
1 import socket
2 import time
3 from threading import Thread
4
5 class Chamber():
6 def __init__(self, tag):
7 #self.ip = '192.168.121.100'
8 #self.port = 2049
9 self.ip = '127.0.0.1'
10 self.port = 31500
11 self.tag = tag
12 self.addr = (self.ip, self.port)
13 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
14 self.sock.connect(self.addr)
15
16 def getTemper(self):
17 self.sock.send(('021?8E03'+self.tag).encode('utf-8'))
18 time.sleep(2)
19 print('Receive blocking', self.tag)
20 data = self.sock.recv(1024)
21 print(data)
22 #self.sock.close()
23
24 def run(self):
25 for i in range(10):
26 self.getTemper()
27
28 cham_1 = Chamber('C_1')
29 cham_2 = Chamber('C_2')
30 Thread(target=cham_1.run).start()
31 Thread(target=cham_2.run).start()