發送和接收數據包
原文:Game Networking系列,作者是Glenn Fiedler,專注於游戲網絡編程相關工作多年。
概述
在之前的網游中的網絡編程系列1:UDP vs. TCP中(推薦先看前面那篇),我們經過討論得出:網游中傳輸數據應該使用UDP而不是TCP。我們選擇UDP是為了不需要等待重發數據包,從而達到數據的實時性。
注意,因為接下來英文原文中所有的代碼是C++寫的,而我是個pythoner,我的計划是:通過理解文章,我用python實現UDP收發數據包、虛擬連接(原文后兩章的內容),在前面的基礎上,最后實現:在UDP上實現可靠、有序、非阻塞的傳輸(當然,也可以直接看原文,連接已經在下面給出)。
所以,我重新規划了下文章的結構,后面的文章我就把它拆分成下面幾章:
- 使用UDP發送和接收數據包
- 非阻塞socket
- 在UDP上建立虛擬連接
- 在UDP上實現可靠、有序、非阻塞的傳輸。
一、發送和接收數據包
在python中,內建標准庫包含了socket,所以我們直接調用標准庫socket,寫兩個腳本,Server代表服務器,Client代表客戶端,代碼如下:
UDPserver.py腳本
# coding:utf-8 import socket UDP_IP = '127.0.0.1' UDP_PORT = 10080 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind((UDP_IP, UDP_PORT)) print '准備接收內容。' while 1: data, addr = sock.recvfrom(1024) # 設置接收數據包的緩存區為1024byte,如果數據包大於這個值,則數據包不會接收大於緩沖區設定值的數據包。 print '從{ip}:{port},接收到內容:{data}'.format(ip=addr[0], port=addr[1], data=data)
UDPclient.py腳本
# coding:utf-8 import socket UDP_IP = '' UDP_PORT = 10080 MESSAGE = 'Hello, world!' print 'UDP 目標IP:', UDP_IP print 'UDP 目標端口:', UDP_PORT print '發送的內容:', MESSAGE sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
上面的代碼有不懂的地方,可以參照我寫的初探socket文章
運行效果:
強調幾點:
-
udp socket發送數據包的時候,不保證數據包是否發送到目的計算機。也就是說:不運行UDPserver.py腳本,先運行UDPclient.py腳本,並不報錯。
-
udp socket 每次發送數據包的時候需要指定IP地址和端口
-
udp socket 接收數據可以獲得發送數據包的計算機的IP和端口
-
udp socket 不會接收大於緩存區的數據包(所以注意:發送時數據包的大小)
最后,可以對照着初探socket中的tcp socket例子,思考上面說的幾點。
TODO
未完待續,本來這章還需要設置非阻塞socket,我覺得如果不說I/O多路復用模型,就不是很好理解設置成非阻塞有什么用。所以,我就把非阻塞socket單弄出來,放在下一章中。