Python的网络编程[0] -> socket[2] -> 利用 socket 建立 TCP/UDP 通信

Socket


 目录

  1. socket 的 TCP/IP 通信基本建立过程
  2. socket 的 UDP 通信基本建立过程
  3. socket 的 UDP 广播式通信基本建立过程
  4. socket 的多线程通信建立过程

  

1 socketTCP/IP通信基本建立过程

socket的TCP/IP通信连接主要包括两个部分,服务端与客户端

1.1 Socket server服务端建立

服务端建立步骤主要有:

  1. 初始化IP地址和端口号;
  2. 生成socket实例,TCP/IP通信选择AF_INET(IPV4),SOCK_STREAM(流套接字类型,数据像字符流一样通过);
  3. bind()函数绑定IP和端口,listen()函数设置最大监听数量;
  4. accept()函数接收client的连接,对于连接的client返回2个参数cs,addr,cs为一个新生成的socket类,用于与连接的client进行通讯,addr包含IP和端口号信息;
  5. 基于生成的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客户端建立

客户端建立步骤主要有:

  1. 初始化IP地址和端口号;
  2. 生成socket实例,TCP/IP通信选择AF_INET(IPV4),SOCK_STREAM(流套接字类型,数据像字符流一样通过);
  3. connect()函数进行IP和端口连接(对应的服务端会利用accept()函数生成一个通信实例进行两者相互之间的通信);
  4. 利用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()

 

2 socketUDP通信基本建立过程

socket的UDP通信连接主要包括两个部分,服务端与客户端

2.1 Socket server服务器建立

服务器建立步骤主要有:

  1. 设置端口号,ip地址可以为空字符(‘’),即表示接受任何地址来的数据报;
  2. 生成socket实例,UDP通信选择AF_INET(IPV4),SOCK_DGRAM(数据报套接字类型,数据以数据报datagrams通过);
  3. bind()函数绑定IP和端口;
  4. 利用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客户端建立

客户端建立步骤主要有:

  1. 生成socket实例,UDP通信选择AF_INET(IPV4),SOCK_STREAM(数据报套接字类型,数据以数据报datagrams通过);
  2. 无需连接直接利用sendto函数向目标ip和端口发送数据;
  3. 利用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 socketUDP广播式通信基本建立过程

3.1 Socket broadcast server服务端建立

服务端建立步骤主要有:

  1. 生成UDP的socket实例;
  2. 利用setsockopt设置socket的broadcast模式为True,地址复用(多个套接字可以同时连接一个端口上);
  3. bind()函数绑定IP和端口;
  4. 利用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客户端建立

客户端建立步骤主要有:

  1. 生成UDP的socket实例;
  2. 利用setsockopt设置socket的broadcast模式为True,地址复用(多个套接字可以同时连接一个端口上);
  3. 无需连接直接利用sendto函数以广播形式向<’broadcast’>和端口发送数据;
  4. 利用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 socket的多线程通信的建立过程

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()

 

posted @ 2017-12-26 16:29  StackLike  阅读(677)  评论(0编辑  收藏  举报