TCP 客戶端與服務(wù)器之間建立連接需要進(jìn)行三次握手 客戶端--->服務(wù)器 服務(wù)器--->客戶端 客戶端--->服務(wù)器,這樣做的好處是可以保證數(shù)據(jù)的完整缺點(diǎn)是慢.
UDP 不需要進(jìn)行三次握手,客戶端與服務(wù)器之間直接往對方臉上丟數(shù)據(jù)不管有沒有接到,優(yōu)點(diǎn)是快缺點(diǎn)是無法保證數(shù)據(jù)的完整. UDP數(shù)據(jù)包一般包含512個(gè)字節(jié),當(dāng)大于512字節(jié)時(shí),可能會出現(xiàn)傳輸不穩(wěn)定的情況。
什么是socket: 這是為了實(shí)現(xiàn)以上的通信過程而建立成來的通信管道,其真實(shí)的代表是客戶端和服務(wù)器端的一個(gè)通信進(jìn)程,雙方進(jìn)程通過socket進(jìn)行通信,而通信的規(guī)則采用指定的協(xié)議。socket只是一種連接模式,不是協(xié)議,tcp,udp,簡單的說(雖然不準(zhǔn)確)是兩個(gè)最基本的協(xié)議,很多其它協(xié)議都是基于這兩個(gè)協(xié)議如,http就是基于tcp的,.用socket可以創(chuàng)建tcp連接,也可以創(chuàng)建udp連接,這意味著,用socket可以創(chuàng)建任何協(xié)議的連接,因?yàn)槠渌鼌f(xié)議都是基于此的。 UDP 傳輸?shù)牧鞒虉D 第一步導(dǎo)入網(wǎng)絡(luò)編程的庫,自帶的 import socket 接著就是要調(diào)用一個(gè)方法 socket.socket(AddressFamily, Type) 就解釋一下參數(shù),別的就不說了
前面的名字,按照自己的喜好來 import socket
# 創(chuàng)建udp socket udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# ... # 使用套接字收/發(fā)數(shù)據(jù)
# 關(guān)閉socket udp_socket.close()
上面的代碼就是對于UDP的一次完整的調(diào)用 套接字使用流程 與 文件的使用流程很類似: 1.創(chuàng)建套接字 2.使用套接字收/發(fā)數(shù)據(jù) 3.關(guān)閉套接字 # # Tello Python3 Control Demo # import threading import socket import sys import time host = '' port = 9000 locaddr = (host, port) # Create a UDP socket sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) tello_address = ('192.168.10.1', 8889) sock.bind(locaddr) def recv(): count = 0 while True: try: data, server = sock.recvfrom(1518) print(data.decode(encoding="utf-8")) except Exception: print('\nExit . . .\n') break print('\r\n\r\nTello Python3 Demo.\r\n') print('Tello: command takeoff land flip forward back left right \r\n up down cw ccw speed speed?\r\n') print('end -- quit demo.\r\n') # recvThread create recvThread = threading.Thread(target=recv) recvThread.start() while True: try: msg = input("") if not msg: break if 'end' in msg: print('...') sock.close() break # Send data msg = msg.encode(encoding="utf-8") sent = sock.sendto(msg, tello_address) except KeyboardInterrupt: print('\n . . .\n') sock.close() break 我直接給出一個(gè)實(shí)例,這是連接Dji教育無人機(jī)的一段代碼,很完整了已經(jīng) sock.bind(locaddr) 使用bind公開一個(gè)端口,使得client可以方便連接 給 創(chuàng)建了一個(gè)無人機(jī)的地址,IP+端口 可以看到上面的tello_address是作為一個(gè)參數(shù)的函數(shù)使用. # 發(fā)送數(shù)據(jù) send_addr = ('192.168.92.190', 7878) udp_socket.sendto(send_data.encode('GBK'), send_addr) 如果是字符集在兩個(gè)目標(biāo)上面不一樣,還可以去更改編碼模式 此時(shí)先下載一個(gè)調(diào)試工具,隨便下載 import socket
def main(): # 創(chuàng)建套接字 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 讀取輸入的數(shù)據(jù) send_data = input('請輸入要發(fā)送的數(shù)據(jù):')
# 發(fā)送數(shù)據(jù) send_addr = ('192.168.92.190', 7878) udp_socket.sendto(send_data.encode('GBK'), send_addr)
# 關(guān)閉 udp_socket.close()
if __name__ == '__main__': main()
http://www.zlmcu.com/document/tcp_debug_tools.html 我上面的軟件沒有調(diào)試出來,我換了一個(gè)軟件,調(diào)試成功 這個(gè)地方用wireshark看一下 選擇內(nèi)部的回環(huán)接口 設(shè)置這里看見是BSD 這個(gè)地方輸入三個(gè)1,a,b 位置信息 可以看到是這個(gè)地址確實(shí)發(fā)了三次信息 打開看看 數(shù)據(jù)31,長度1 可以用ifconfig看看自己的ip import socket
def main():
# 創(chuàng)建套接字 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 綁定一個(gè)本地信息 localaddr = ("", 8080) udp_socket.bind(localaddr)
# 接收數(shù)據(jù) recv_data = udp_socket.recvfrom(1024)
# recv_data是一個(gè)元組(接收到的數(shù)據(jù), (發(fā)送方的IP, port)) recv_msg = recv_data[0] # 存儲接收到的數(shù)據(jù) send_addr = recv_data[1] # 存儲發(fā)送方的地址
# 打印收到的消息 # print(recv_data) print("%s:%s" % (str(send_addr), recv_msg.decode('GBK')))
# 關(guān)閉 udp_socket.close()
if __name__ == '__main__': main() 這段代碼是接收代碼,寫的很明白 udp端口綁定
什么時(shí)候需要綁定端口呢? 一般來說,如果要做成一個(gè)服務(wù)端的應(yīng)用程序的話,是需要綁定固定端口的。 python3中的編碼轉(zhuǎn)換
str.encode()
bytes.decode()
|
|