Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python UDP聊天,服务器也可以聊天_Python_Sockets_Udp_Chat_Chatroom - Fatal编程技术网

Python UDP聊天,服务器也可以聊天

Python UDP聊天,服务器也可以聊天,python,sockets,udp,chat,chatroom,Python,Sockets,Udp,Chat,Chatroom,我在GitHub上发现了一个非常简单的开放源码:同一个Python脚本可以用作服务器或客户端 import socket import threading import queue import sys import random import os #Client Code def ReceiveData(sock): while True: try: data,addr = sock.recvfrom(1024) p

我在GitHub上发现了一个非常简单的开放源码:同一个Python脚本可以用作服务器或客户端

import socket
import threading
import queue
import sys
import random
import os


#Client Code
def ReceiveData(sock):
    while True:
        try:
            data,addr = sock.recvfrom(1024)
            print(data.decode('utf-8'))
        except:
            pass

def RunClient(serverIP):
    host = socket.gethostbyname(socket.gethostname())
    port = random.randint(6000,10000)
    print('Client IP->'+str(host)+' Port->'+str(port))
    server = (str(serverIP),5000)
    s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    s.bind((host,port))

    name = input('Please write your name here: ')
    if name == '':
        name = 'Guest'+str(random.randint(1000,9999))
        print('Your name is:'+name)
    s.sendto(name.encode('utf-8'),server)
    threading.Thread(target=ReceiveData,args=(s,)).start()
    while True:
        data = input()
        if data == 'qqq':
            break
        elif data=='':
            continue
        data = '['+name+']' + '->'+ data
        s.sendto(data.encode('utf-8'),server)
    s.sendto(data.encode('utf-8'),server)
    s.close()
    os._exit(1)
#Client Code Ends Here


#Server Code
def RecvData(sock,recvPackets):
    while True:
        data,addr = sock.recvfrom(1024)
        recvPackets.put((data,addr))

def RunServer():
    host = socket.gethostbyname(socket.gethostname())
    port = 5000
    print('Server hosting on IP-> '+str(host))
    s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    s.bind((host,port))
    clients = set()
    recvPackets = queue.Queue()

    print('Server Running...')

    threading.Thread(target=RecvData,args=(s,recvPackets)).start()

    while True:
        while not recvPackets.empty():
            data,addr = recvPackets.get()
            if addr not in clients:
                clients.add(addr)
                continue
            clients.add(addr)
            data = data.decode('utf-8')
            if data.endswith('qqq'):
                clients.remove(addr)
                continue
            print(str(addr)+data)
            for c in clients:
                if c!=addr:
                    s.sendto(data.encode('utf-8'),c)

    s.close()
#Serevr Code Ends Here

if __name__ == '__main__':
    if len(sys.argv)==1:
        RunServer()
    elif len(sys.argv)==2:
        RunClient(sys.argv[1])
    else:
        print('Run Serevr:-> python Chat.py')
        print('Run Client:-> python Chat.py <ServerIP>')
导入套接字
导入线程
导入队列
导入系统
随机输入
导入操作系统
#客户端代码
def接收数据(sock):
尽管如此:
尝试:
数据,addr=sock.recvfrom(1024)
打印(数据解码('utf-8'))
除:
通过
def RunClient(服务器IP):
host=socket.gethostbyname(socket.gethostname())
端口=random.randint(600010000)
打印('客户端IP->'+str(主机)+'端口->'+str(端口))
服务器=(str(serverIP),5000)
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s、 绑定((主机、端口))
name=input('请在此处填写您的姓名:')
如果名称=“”:
name='Guest'+str(random.randint(10009999))
打印('您的姓名是:'+姓名)
s、 sendto(name.encode('utf-8'),服务器)
threading.Thread(target=ReceiveData,args=(s,).start()
尽管如此:
数据=输入()
如果数据==“qqq”:
打破
elif数据=='':
持续
数据='['+name+']'+'->'+数据
s、 发送到(数据编码('utf-8'),服务器)
s、 发送到(数据编码('utf-8'),服务器)
s、 关闭()
操作系统退出(1)
#客户端代码到此结束
#服务器代码
def RecvData(插座、recvPackets):
尽管如此:
数据,addr=sock.recvfrom(1024)
recvPackets.put((数据,地址))
def RunServer():
host=socket.gethostbyname(socket.gethostname())
端口=5000
打印('IP上的服务器主机->'+str(主机))
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s、 绑定((主机、端口))
clients=set()
recvPackets=queue.queue()
打印('服务器正在运行…')
threading.Thread(target=RecvData,args=(s,recvPackets)).start()
尽管如此:
而不是recvPackets.empty():
data,addr=recvPackets.get()
如果addr不在客户端中:
clients.add(addr)
持续
clients.add(addr)
数据=数据。解码('utf-8')
如果data.endswith('qqq'):
客户端。删除(添加)
持续
打印(str(addr)+数据)
对于客户端中的c:
如果c=地址:
s、 发送到(数据编码('utf-8'),c)
s、 关闭()
#Serevr代码到此结束
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
如果len(sys.argv)==1:
RunServer()
elif len(系统参数)=2:
RunClient(sys.argv[1])
其他:
打印('runserevr:->python Chat.py')
打印('runclient:->python Chat.py')
从图中可以看出,它工作得非常好:

但我的目标是让服务器也加入聊天


UDP聊天室在作为服务器工作时是否也可以让服务器作为客户端

要让服务器同时运行客户端,您可以在调用
RunServer()
之前将这一行插入代码的
\uuuu main\uuu
部分:

    threading.Thread(target=RunClient,args=('127.0.0.1',)).start()
这将启动一个线程,该线程与服务器的事件循环并行运行
RunClient('127.0.0.1')

但是,在代码正常工作之前,您还需要修复代码中的一些其他问题。特别是:

RunServer()
的顶部,您将
host
设置为服务器计算机上一个网络接口卡的IP地址。这意味着服务器只能在一个网络接口上接受传入的TCP连接,这意味着(除非该网络接口恰好是内部/环回接口),服务器将不会从其自己的客户端线程接受到
127.0.0.1
的连接。解决这一问题的简单方法是将主机设置为空字符串,这样服务器将在所有本地网络接口上接受传入的TCP连接,问题就消失了

def RunServer():
    host = '' # was:  socket.gethostbyname(socket.gethostname())
    [...]
第二个问题是服务器的事件循环正忙着等待,导致服务器进程在整个运行过程中不必要地消耗了100%的CPU核心。那效率太低了。该问题的原因在这里,在
RunServer()内部

请注意,在Python
Queue
类中,对
get()
的调用会一直阻塞,直到有更多数据要接收,从而防止CPU旋转。但是在上面的代码中,
get()

修复方法很简单,只需删除
,而不完全删除recvPackets.empty()
行,这样即使队列为空,也会调用
get()
get()
只有在有数据返回时才会返回

while True:
   data,addr = recvPackets.get()
   [...]

要使服务器同时运行客户端,您可以在代码的
\uuuu main\uuu
部分中调用
RunServer()
之前插入此行:

    threading.Thread(target=RunClient,args=('127.0.0.1',)).start()
这将启动一个线程,该线程与服务器的事件循环并行运行
RunClient('127.0.0.1')

但是,在代码正常工作之前,您还需要修复代码中的一些其他问题。特别是:

RunServer()
的顶部,您将
host
设置为服务器计算机上一个网络接口卡的IP地址。这意味着服务器只能在一个网络接口上接受传入的TCP连接,这意味着(除非该网络接口恰好是内部/环回接口),服务器将不会从其自己的客户端线程接受到
127.0.0.1
的连接。解决这一问题的简单方法是将主机设置为空字符串,这样服务器将在所有本地网络接口上接受传入的TCP连接,问题就消失了

def RunServer():
    host = '' # was:  socket.gethostbyname(socket.gethostname())
    [...]
第二个问题是服务器的事件循环正忙着等待,导致服务器进程在整个运行过程中不必要地消耗了100%的CPU核心。那太不像话了