一、基本概念

1.嵌套字

套接字是计算机网络数据结构,它体现了上节中所描述的“通信端点”的概念。在任何类型的通信开始之前,网络应用程序必须创建套接字。可以将它们比作电话插孔,没有它将无法进行通信。

2.套接字地址:主机-端口对

如果一个套接字像一个电话插孔——允许通信的一些基础设施,那么主机名和端口号就像区号和电话号码的组合。然而,拥有硬件和通信的能力本身并没有任何好处,除非你知道电话打给谁以及如何拨打电话。一个网络地址由主机名和端口号对组成,而这是网络通信所需要的。有效的端口号范围为0~65535(尽管小于1024的端口号预留给了系统)。

二、socket函数

要创建套接字,必须使用socket.socket()函数,它一般的语法为:socket(socket_family, socket_type, protocol=0)

其中,socket_family是AF_UNIX或AF_INET(如前所述),socket_type是SOCK_STREAM或SOCK_DGRAM(也如前所述)。protocol通常省略,默认为0。

所以,为了创建TCP/IP套接字,可以用下面的方式调用socket.socket()。

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

同样,为了创建UDP/IP套接字,需要执行以下语句。

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

1.创建TCP服务器和客户端

伪代码如下:

1 ss = socket() #创建服务器套接字
2 ss.bind() #套接字与地址绑定
3 ss.listen() #监听连接(开启监听)
4 inf_loop: #服务器无限循环
5 cs = ss.accept() #接受客户端连接
6 comm_loop: #通信循环
7 cs.recv()/cs.send() #对话(接收/发送)
8 cs.close() #关闭客户端套接字
9 ss.close() #关闭服务器套接字#(可选)

所有套接字都是通过使用socket.socket()函数来创建的。因为服务器需要占用一个端口并等待客户端的请求,所以它们必须绑定到一个本地地址。因为TCP是一种面向连接的通信系统,所以在TCP服务器开始操作之前,必须安装一些基础设施。特别地,TCP服务器必须监听(传入)的连接。一旦这个安装过程完成后,服务器就可以开始它的无限循环。

调用accept()函数之后,就开启了一个简单的(单线程)服务器,它会等待客户端的连接。默认情况下,accept()是阻塞的,这意味着执行将被暂停,直到一个连接到达。另外,套接字确实也支持非阻塞模式。一旦服务器接受了一个连接,就会返回(利用accept())一个独立的客户端套接字,用来与即将到来的消息进行交换。使用新的客户端套接字类似于将客户的电话切换给客服代表。当一个客户电话最后接进来时,主要的总机接线员会接到这个电话,并使用另一条线路将这个电话转接给合适的人来处理客户的需求。

【示例2-2】 python 3 TCP时间戳服务器:

1 #!/usr/bin/env python
2 from socket import *
3 from time importctime4
5 HOST = ''
6 PORT = 21567
7 BUFSIZE = 1024
8 ADDR =(HOST,PORT)9
10
11 tcpSerSock =socket(AF_INET,SOCK_STREAM)12 tcpSerSock.bind(ADDR) #绑定
13 tcpSerSock.listen(5) #开启监听
14
15 whileTrue:16 print('waiting for connecting...')17 tcpCliSock,addr =tcpSerSock.accept()18 print('...connected from:',addr)19
20 whileTrue:21 data =tcpCliSock.recv(BUFSIZE).decode()22 print('data:',data)23 if notdata:24 break
25
26 tcpCliSock.send(('[%s] %s' %(ctime(), data)).encode())27 tcpCliSock.close()28 tcpSerSock.close()
View Code

【示例2-4】 Python 3 TCP时间戳客户端

如何用python打网络电话 python 网络电话_服务器

1 #!/usr/bin/env python
2 from socket import *
3 from time importctime4
5 HOST = '172.10.11.142'
6 PORT = 21567
7 BUFSIZE = 1024
8 ADDR =(HOST,PORT)9
10
11 tcpCliSock =socket(AF_INET,SOCK_STREAM)12 tcpCliSock.connect(ADDR)13
14 whileTrue:15 data = input('please your information......')16 if notdata:17 break
18 tcpCliSock.send(data.encode())19 data =tcpCliSock.recv(BUFSIZE).decode()20 if notdata:21 break
22 print(data)23 tcpCliSock.close()
View Code

2.创建UDP时间戳服务器

伪代码如下:

1 ss = socket() #创建服务器套接字
2 ss.bind() #绑定服务器套接字
3 inf_loop: #服务器无限循环
4 cs = ss.recvfrom()/ss.sendto() #关闭(接收/发送)
5 ss.close() #关闭服务器套接字

【示例2-6】 UDP时间戳服务器(tsUserv.py)

如何用python打网络电话 python 网络电话_服务器

如何用python打网络电话 python 网络电话_服务器_03

1 #!/usr/bin/env python
2 from socket import *
3 from time importctime4
5 HOST = ''
6 PORT = 21567
7 BUFSIZE = 1024
8 ADDR =(HOST,PORT)9
10 udpSerSock =socket(AF_INET, SOCK_DGRAM)11 udpSerSock.bind(ADDR)12 #tcpSerSock.listen(5) #TCP开启监听
13
14 whileTrue:15 print('waiting for connecting...')16 data,addr =udpSerSock.recvfrom(BUFSIZE)17 print('data:',data.decode())18 data_tmp =data.decode()19 udpSerSock.sendto(('[%s] %s'%(ctime(),data_tmp)).encode(),addr)20 print('......received from and returned to:',addr)21 udpSerSock.close()
View Code

【示例2-7】 UDP时间戳服务器(tsUserv.py)

如何用python打网络电话 python 网络电话_服务器

如何用python打网络电话 python 网络电话_服务器_03

1 #!/usr/bin/env python
2 from socket import *
3 from time importctime
4
5 HOST = '172.10.11.142'
6 PORT = 21567
7 BUFSIZE = 1024
8 ADDR =(HOST,PORT)
9 udpCliSock =socket(AF_INET,SOCK_DGRAM)
10
11 whileTrue:
12 data = input('please your information......')
13 if notdata:
14 break
15 udpCliSock.sendto(data.encode(),ADDR)
16 data,ADDR =udpCliSock.recvfrom(BUFSIZE)
17 if notdata:
18 break
19 print(data.decode())
20 udpCliSock.close()
View Code