Нужна помощь в мгновенной отправке моего сокетного мессенджера на Python
Я уверен, что есть более простые способы с определенными модулями Python, но для назначения мне нужно создать программу, которая может выступать в роли клиента / сервера. На данный момент у меня это работает до такой степени, что я могу отправить сообщение, только если получатель ответил. Мне нужно просто отправить и появиться на соответствующем клиент / серверном терминале при нажатии Enter. Любая помощь будет принята с благодарностью!
Это фотографии того, что происходит на данный момент
import sys
import socket
import getopt
def usage(script_name):
print('Usage: py' + script_name + '-l' +' <port number>' + '[<server>]')
def sockObj():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
return sock
def serversockConn(serversocket,port):
serversocket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# bind the serversocket to address
serversocket.bind(('',int(port)))
# enable a server to accept connections
serversocket.listen(5)
# wait for a connection and accept it
sock,addr = serversocket.accept()
return sock
def connToServersock(sock,server, port):
# connect to a serversocket
if server:
sock.connect((server, int(port)))
else:
sock.connect(('localhost', int(port)))
return sock
if __name__ == '__main__':
## get the command line arguments
try:
options, non_option_args = getopt.getopt(sys.argv[1:],'l')
except getopt.GetoptError as err:
print(err)
sys.exit(2)
#check if '-l' is present in command line agrument
serverSide = False
for opt,arg in options:
if opt == "-l":
serverSide = True
# port number
port = non_option_args[0]
# server address
server = None
hostLen = len(non_option_args)
if hostLen == 2:
server = non_option_args[1]
# create a communicator object, and make a connection between server and client
# server
if serverSide:
serversocket = sockObj()
sock = serversockConn(serversocket,port)
# client
else:
sock = sockObj()
sock = connToServersock(sock,server,port)
while True:
## read a message from standard input
message = sys.stdin.readline().encode()
if len(message) != 0:
sock.send(message)
return_msg = sock.recv( 1024 )
if return_msg:
print("Message recieved: " + return_msg.decode())
else:
print("Other side shut down")
else:
try:
sock.shutdown(socket.SHUT_WR)
sock.close()
except:
pass
1 ответ
Я думаю, что ваша проблема в том, что в вашем цикле событий есть два места, где вы блокируете:
message = sys.stdin.readline().encode()
Здесь вы блокируете до тех пор, пока пользователь не нажмет кнопку возврата - в течение этого времени ваша программа не сможет отвечать на любые данные, полученные по сети, потому что она заблокирована в ожидании данных от стандартного ввода.
... а также:
return_msg = sock.recv( 1024 )
Здесь вы ожидаете получения данных из сети - в течение этого времени ваша программа не может отвечать на любые данные, полученные от stdin, потому что она заблокирована в ожидании данных из сети.
В идеале вы хотели бы, чтобы ваша программа ожидала как стандартного, так и сетевого трафика одновременно - то есть блокировала его до тех пор, пока пользователь не нажмет return, или не будут получены некоторые сетевые данные, в зависимости от того, что наступит раньше.
Самый простой способ добиться такого поведения - использовать select()
; его цель - блокировать, пока хотя бы один из нескольких файловых дескрипторов не будет готов к действию. (Обратите внимание, однако, что Windows не поддерживает использование select()
на stdin, поэтому, если ваша программа должна работать под Windows, вам, вероятно, придется вместо этого создавать второй поток).
Для реализации цикла событий используется select()
, добавлять import select
в начало вашего скрипта, затем замените цикл обработки событий на что-то вроде этого:
while True:
## block here until either sock or sys.stdin has data ready for us
readable, writable, exceptional = select.select([sock, sys.stdin], [], [])
if sys.stdin in readable:
## read a message from standard input
message = sys.stdin.readline().encode()
if len(message) != 0:
sock.send(message)
if sock in readable:
## read a message from the network
try:
return_msg = sock.recv( 1024 )
if (return_msg):
print("Message received: " + return_msg.decode())
else:
print("Other side shut down")
break
except:
print("recv() threw an exception")
break