9.2 Socket编程

  远程管理软件和黑客软件大多依赖于Socket来实现特定功能,前几年流行的端口反弹更是把这项技术发挥到了极致。

  如前所述,UDP和TCP是网络体系结构的传输层运行的两大重要协议,其中,TCP适用于对效率要求相对低而准确性要求相对高的场合,如文本传输、电子邮件等;而UDP适用于对效率要求相对高,对准确性要求相对低的场合,如视频在线点播、网络语音通话等。在Python中,主要使用socket模块来支持TCP和UDP编程。

  9.2.1 UDP编程

  在很多年以前普通家庭还没有手机、电话、传呼机的时候,主要靠信件往来联系,发信人提哦啊好收信人地址然后把信件寄出去就可以了,但是没法保证对方一定能收到这封信(例如对方换了地址),也不能保证不同时间的几封信按照发出的顺序到达目的地。UDP的工作过程就类似于邮寄普通信件,它属于无连接协议,在UDP编程时不需要首先建立连接,而是直接向接收方发送信息。UDP也不提供应答和重传机制,无法保证数据一定鞥能够到达目的地。UDP最大的优点是效率高,其首部中只包含双发地址于校验等很少的字段,额外开销很小。UDP编程经常用到的socket模块方法如下。

  (1)socket([family[,type[,proto]]] :创建一个Socket对象,其中family为socket.AF_INET表示IPv4,AF_INET6表示IPv6;type为SOCK_STREAM表示使用TCP,SOCK_DGRAM表示使用UDP。

  (2)sendto(string,address):把string指定的内容发送给address指定的地址,其中address是一个包含接收方主机IP地址的应用进程端号的元组,格式为(IP地址,端口号)。

  (3)recvfrom(bufsize[,flags]):接收数据。

  下面通过一个示例来简单了解一个如何使用UDP进行网络通信。

  发送端发送一个字符串,假设接收端在本机5000端口进行监听,并显示接受的内容,如果收到字符串'bye'(忽略大小写)则结束监听。

  接收端代码:

 1 import socket
 2 
 3 #使用IPv4协议,使用UDP传输数据
 4 s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
 5 
 6 #绑定端口和端口好,空字符串表示本机任何可用IP地址
 7 s.bind('',5000)
 8 
 9 while True:
10     data,addr = s.recvfrom(1024)
11 
12     #显示接收到的内容
13     print('received message:{0} from PORT{1} on {2}'.format(data.decode(),addr[1],addr[0]))
14 
15     if data.decode().lower() == 'bye':
16         break
17 
18 s.close()

  发送端代码:

import socket
import sys

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

#假设192.168.1.103是接收端机器的IP地址
s.sendto(sys.argv[1].encode(),('192.168.1.103',5000))

s.close()

  将上面的代码分别保存为receiver.py和sender.py,然后首先启动一个命令提示符环境并运行接收端程序,这时接收端程序处于阻塞状态,接下来再启动一个新的命令体书法环境并运行发送端程序,此时会看到接收端程序继续运行并显示接收到的内容以及发送端程序所在计算机IP地址和占用的端口号。当发送端发送字符串'bye'后,接收单程序结束,此后再次运行发送端程序时接收端没有任何反应,但发送端程序也并不报错。这就是UDP的特点,即“尽最大努力传输”,并不能保证非常好的服务质量。

  可以使用下面的Python代码来获取本机的IP地址和网卡的物理地址。

 1 ip = socket.gethostbyname(socket.gethostname())  #本机IP地址
 2 node = uuid.getnode()
 3 print('node:',node)
 4 
 5 macHex = uuid.UUID(int=node).hex[-12:]
 6 mac = []
 7 print(macHex)
 8 for i in range(len(macHex))[::2]:
 9     mac.append(macHex[i:i+2])
10 
11 mac1 = ':'.join(mac)                          #网卡的物理地址
12 
13 print('IP:',ip)
14 print('MAC:',mac1)

  拓展知识:发送数据时,如果目标IP地址中最后一组数字是255,表示广播地址,也就是说局域网内的所有主机都会受到信息。

猜你喜欢

转载自www.cnblogs.com/avention/p/8974112.html
9.2