基於UDP協議的socket套接字編程

1、UDP套接字簡單示例

1.1 服務端

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 數據報協議-》UDP
server.bind(('127.0.0.1', 8080))

while True:
    data, client_addr = server.recvfrom(1024)
    print('===>', data, client_addr)
    server.sendto(data.upper(), client_addr)

server.close()

2、客戶端

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 數據報協議-》UDP

while True:
    msg = input('>>: ').strip()  # msg=''
    client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080))
    data, server_addr = client.recvfrom(1024)
    print(data)

client.close()
  • UDP是無連接的,先啓動哪一端都不會報錯編程

  • UDP協議是數據報協議,發空的時候也會自帶報頭,所以客戶端輸入空,服務端也能收到socket

3、UPD套接字無粘包問題

3.1 服務端

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 數據報協議-》udp
server.bind(('127.0.0.1', 8080))

data, client_addr = server.recvfrom(1024)  # b'hello'==>b'h'
print('第一次:', client_addr, data)

data, client_addr = server.recvfrom(1024)  # b'world' =>b'world'
print('第二次:', client_addr, data)
#
# data,client_addr=server.recvfrom(1024)
# print('第三次:',client_addr,data)

server.close()

3.2 客戶端

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 數據報協議-》udp

client.sendto('hello'.encode('utf-8'), ('127.0.0.1', 8080))
client.sendto('world'.encode('utf-8'), ('127.0.0.1', 8080))
# client.sendto(''.encode('utf-8'),('127.0.0.1',8080))

client.close()
  • UPD協議通常不用於傳輸大數據。大數據

  • UDP套接字雖然沒有粘包問題,可是不能替代TCP套接字,由於UPD協議有一個缺陷:若是數據發送的途中,數據丟失,則數據就丟失了,而TCP協議則不會有這種缺陷,所以通常UPD套接字用戶可有可無的數據發送,例如qq聊天。ui

4、qq聊天

  • 因爲UDP無鏈接,因此能夠同時多個客戶端去跟服務端通訊

4.1 服務端

#_*_coding:utf-8_*_
__author__ = 'nick'
import socket
ip_port = ('127.0.0.1', 8081)
UDP_server_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  #買手機
UDP_server_sock.bind(ip_port)

while True:
    qq_msg, addr = UDP_server_sock.recvfrom(1024)
    print('來自[%s:%s]的一條消息:\033[1;44m%s\033[0m' %
          (addr[0], addr[1], qq_msg.decode('utf-8')))
    back_msg = input('回覆消息: ').strip()

    UDP_server_sock.sendto(back_msg.encode('utf-8'), addr)

4.2 客戶端1

#_*_coding:utf-8_*_
__author__ = 'nick'
import socket
BUFSIZE = 1024
UDP_client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

qq_name_dic = {
    '狗哥alex': ('127.0.0.1', 8081),
    '瞎驢': ('127.0.0.1', 8081),
    '一棵樹': ('127.0.0.1', 8081),
    '武大郎': ('127.0.0.1', 8081),
}

while True:
    qq_name = input('請選擇聊天對象: ').strip()
    while True:
        msg = input('請輸入消息,回車發送: ').strip()
        if msg == 'quit': break
        if not msg or not qq_name or qq_name not in qq_name_dic: continue
        UDP_client_socket.sendto(msg.encode('utf-8'), qq_name_dic[qq_name])

        back_msg, addr = UDP_client_socket.recvfrom(BUFSIZE)
        print('來自[%s:%s]的一條消息:\033[1;44m%s\033[0m' %
              (addr[0], addr[1], back_msg.decode('utf-8')))

UDP_client_socket.close()

4.3 客戶端2

#_*_coding:utf-8_*_
__author__ = 'nick'
import socket
BUFSIZE = 1024
UDP_client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

qq_name_dic = {
    '狗哥alex': ('127.0.0.1', 8081),
    '瞎驢': ('127.0.0.1', 8081),
    '一棵樹': ('127.0.0.1', 8081),
    '武大郎': ('127.0.0.1', 8081),
}

while True:
    qq_name = input('請選擇聊天對象: ').strip()
    while True:
        msg = input('請輸入消息,回車發送: ').strip()
        if msg == 'quit': break
        if not msg or not qq_name or qq_name not in qq_name_dic: continue
        UDP_client_socket.sendto(msg.encode('utf-8'), qq_name_dic[qq_name])

        back_msg, addr = UDP_client_socket.recvfrom(BUFSIZE)
        print('來自[%s:%s]的一條消息:\033[1;44m%s\033[0m' %
              (addr[0], addr[1], back_msg.decode('utf-8')))

UDP_client_socket.close()

4.4 運行結果

  • 服務端運行結果

125-基於UDP協議的套接字編程-聊天1.png?x-oss-process=style/watermark

  • 客戶端1運行結果

125-基於UDP協議的套接字編程-聊天2.png?x-oss-process=style/watermark

  • 客戶端2運行結果

125-基於UDP協議的套接字編程-聊天3.png?x-oss-process=style/watermark

相關文章
相關標籤/搜索