疯狂飞艇

当前位置:疯狂飞艇 > IT教程

UDP编程

时间:2019-11-23 03:35:01来源:金橙教程网 作者:admin8 阅读:51次
 

udp编程

测试命令
#windows查找UDP是否启动端口
> netstat -anp udp | find "9999"
> netstat -anbp udp | findstr 9999

UDP服务端编程

在这里插入图片描述

  • 创建socket对象。socket.SOCK_DGRAM

  • 绑定IP和Port,bind()方法

  • 传输数据

    • 接收数据,socket.recvfROM(bufsize[,flags]),获得一个二元组(String,address)
    • 发送数据,socket.sendto(string,address)发给某疯狂飞艇某信息
  • 释放资源

import socket
Server=socket.socket(type=socket.SOCK_DGRAM)
server.bind(('172.22.141.176',9999))
DATa=server.recv(1024)
print(data)
data=server.recvfrom(1024)
print(data)
server.sendto(b'110110',('172.22.141.176',10000))
server.close()

在这里插入图片描述

在这里插入图片描述

UDP客户端编程流程

  • 创建socket对象,socket.SOCK_DGRAM
  • 发送数据,socket.sendto(string,address)发送给某疯狂飞艇某信息
  • 接收数据,socket.recvfrom(bufsize[,flags]),获得一个二元组(string,address)
  • 释放资源
import socket
client=socket.socket(type=socket.SOCK_DGRAM)
raddr=('172.22.141.176',11111)

client.connect(raddr)
client.sendto(b'1008611',raddr)
client.send(b'132132323')
data=client.recvfrom(1024)
print(data)
data=client.recv(1024)
print(data)

client.close()

在这里插入图片描述

注意:UDP是无连接协议,所以可以只有任何一端,例如客户端数据发往服务端,服务端存在与否无所谓。

UDP编程bind、connect、send、sendto、recv、recvfrom方法使用

UDP的socket对象创建后,是没有占用本地疯狂飞艇和端口的。

方法 说明
bind方法 可以指定本地疯狂飞艇和端口laddr,会立即占用
connect方法 可以立即占用本地疯狂飞艇和端口laddr,填充远端疯狂飞艇和端口raddr
sendto方法 可以立即占用本地疯狂飞艇和端口laddr,并发数据发往指定远端,只有有了本地绑定端口,sendto就可以向任何远端发送数据
send方法 需要和connect方法配合,可以使用已经从本地端口把数据发往raddr指定的远端
recv方法 要求一定要在占用了本地端口后,返回接收的数据
recvfrom方法 要求一定要占用本地端口后,返回接收的数据和对端疯狂飞艇的二元组
  • UDP群聊服务端
import socket
import threading
class ChatUdpServer:
    def __init__(self,ip='0.0.0.0',port=11112):
        self.Ipaddr=ip,port
        self.sock=socket.socket(type=socket.SOCK_DGRAM)
        self.clients=set()
        self.event=threading.Event()
        self.lock=threading.Lock()
    def start(self):
        self.sock.bind(self.ipaddr)
        threading.Thread(target=self.recv).start()
    def recv(self):
        while not self.event.is_set():
            try:
                data,other=self.sock.recvfrom(1024)
                print(data)
                if data==b'quit':
                    with self.lock:
                        self.clients.remove(other)
                    continue
                with self.lock:
                    self.clients.add(other)
                with self.lock:
                    for i in self.clients:
                        self.sock.sendto(data,i)
            except:
                print('ERROR')
    def stop(self):
        self.event.set()
        self.clients.clear()
        try:
            self.sock.close()
        except:
            print('over')
        finally:
            print('over')
chat=ChatUdpServer()
chat.start()
while True:
    cmd=input(">>>").strip()
    if cmd=='quit':
        chat.stop()
        break
    print(threading.enumerate())
  • UDP客户端
import socket
import threading
import time
class ChatUdpClient:
    def __init__(self,ip='172.22.141.176',port=11113):
        self.sock=socket.socket(type=socket.SOCK_DGRAM)
        self.ipadd=ip,port
        self.event=threading.Event()
        self.lock=threading.Lock()
    def start(self):
        self.sock.connect(self.ipadd)
        threading.Thread(target=self.send).start()
        threading.Thread(target=self.recv).start()
    def send(self):
        while not self.event.is_set():
            with self.lock:
                data=input("你说话呀:").strip().encode()
                self.sock.sendto(data,self.ipadd)
    def recv(self):
        while not self.event.is_set():
            message=self.sock.recvfrom(1024)
            print(message)
    def stop(self):
        self.event.set()
        self.sock.close()
chat=ChatUdpClient()
chat.start()
while True:
    time.sleep(10)
    cmd=input('>>>').strip()
    if cmd=='quit':
        chat.stop()
    print(threading.enumerate())

上面的例子并不完善,如果客户端断开了,服务端不知道,每一个服务端还需要对所有客户端发送数据,包括已经断开的客户端

服务端代码改进

增加心跳机制heartbeat机制或ack机制,这些机制同样用在TCP通信的时候。

心跳,就是一端定时发往另一端的信息。

ack即相应,一端收到另一端的信息后返回的确认信息。

心跳机制:

1、一般来说是客户端定时发往服务端的,服务端并不需要ack回复客户端,只需要记录该客户端活着就行了。

2、如果是服务端定时发往客户端的,一般需要客户端ack相应来表示活着,如果没有收到ack的客户端,服务端移除其信息,这种实现较为复杂,用的较少

3、双向发心跳

import socket
import threading
import datetime
class ChatUdpServer:
    def __init__(self,ip='172.22.141.176',port=11113,interval=10):
        self.ipaddr=ip,port
        self.sock=socket.socket(type=socket.SOCK_DGRAM)
        self.clients=dict()
        self.event=threading.Event()
        self.lock=threading.Lock()
        self.interval=interval
    def start(self):
        self.sock.bind(self.ipaddr)
        threading.Thread(target=self.recv).start()
    def recv(self):
        while not self.event.is_set():
            start = datetime.datetime.now().timestamp()
            try:
                data,other=self.sock.recvfrom(1024)
                if data.strip()==b'^bbb^':
                    self.clients[other]=start
                    continue
                elif data==b'quit':
                    with self.lock:
                        self.clients.pop(other)
                    continue
                with self.lock:
                    self.clients[other]=start
                with self.lock:
                    fail=set()
                    print(fail)
                    for i,k in self.clients.items():
                        print(self.clients)
                        print(k)
                        print(start)
                        if start-k>self.interval:
                            fail.add(i)
                        else:
                            self.sock.sendto(data,i)
                    for c in  fail:
                        self.clients.pop(c)
            except:
                print('error')
    def stop(self):
        self.event.set()
        self.clients.clear()
        try:
            self.sock.close()
        except:
            print('over')
        finally:
            print('over')
chat=ChatUdpServer()
chat.start()
while True:
    cmd=input(">>>").strip()
    if cmd=='quit':
        chat.stop()
        break
    print(threading.enumerate())
  • 客户端增加心跳机制
import socket
import threading
import time
class ChatUdpClient:
    def __init__(self,ip='172.22.141.176',port=11113):
        self.sock=socket.socket(type=socket.SOCK_DGRAM)
        self.ipadd=ip,port
        self.event=threading.Event()
        self.lock=threading.Lock()
    def start(self):
        self.sock.connect(self.ipadd)
        threading.Thread(target=self.send).start()
        threading.Thread(target=self.recv).start()
        threading.Thread(target=self.heartbeat).start()
    def heartbeat(self):
        while not self.event.wait(5):
            self.sock.send(b'^^bb^^')
    def send(self):
        while not self.event.is_set():
            with self.lock:
                data=input("你说话呀:").strip().encode()
                self.sock.sendto(data,self.ipadd)
    def recv(self):
        while not self.event.is_set():
            message=self.sock.recvfrom(1024)
            print(message)
    def stop(self):
        self.event.set()
        self.sock.close()
chat=ChatUdpClient()
chat.start()
while True:
    time.sleep(10)
    cmd=input('>>>').strip()
    if cmd=='quit':
        chat.stop()
    print(threading.enumerate())

相关阅读

用笔记本编程,强烈建议外接一个大屏幕显示器!(最好用HDMI

http://item.jd.com/1097163.htmlhttp://item.jd.com/1102166.html注意:(1)我的笔记本型号是Thankpad E430C,视频接口有VGA和HDMI两种

黑基网博客——网络安全、工具软件、无线智能设备、编

黑基网博客——网络安全、工具软件、无线智能设备、编程开发、网赚分享与交流基地黑基网博客:http://www.heijiwang.cn手机黑基网:h

java可视化编程

/** * */ package com.netty.client; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.

[转]三种编程命名规则:驼峰命名法,帕斯卡命名法,匈牙利命

三种流行的命名法则 目前,业界共有四种命名法则:驼峰命名法、匈牙利命名法、帕斯卡命名法和下划线命名法,其中前三种是较为流行的命

C++ Socket编程步骤

  转自http://www.cnblogs.com/chencaiming/p/7249904.html sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_

分享到:

IT相关

程序相关

推荐文章

热门文章

疯狂飞艇官网疯狂飞艇网址疯狂飞艇平台疯狂飞艇app疯狂飞艇下载