Приложение Python 3 Sockets прекращает отправку данных
У меня была программа, в которой всякий раз, когда кто-то нажимал клавишу ввода, не печатая что-либо, программа переставала принимать данные.
#Client
import socket
from time import sleep
import time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = 'localhost'
port = 9990
s.connect((host, port))
print('connecting')
global ab
try:
ab = input('enter input')
except Exception as eb:
ab = 'hello'
s.sendall(ab.encode())
while True:
global hi
try:
hi = input('enter input')
except Exception as b:
hi = input('enter input')
try:
dataNew = s.recv(4024)
s.sendall(hi.encode())
except Exception as be:
print('try again')
if dataNew:
print(dataNew)
if not dataNew:
print('error')
break
Сервер ниже:
#Server
import socket
host = 'localhost'
port = 9990
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except Exception as e:
print("Error creating socket")
try:
s.bind((host, port))
print('Binding socket')
s.listen(10)
print('listening')
except Exception as e:
print('Error creating server')
def mainInput():
while True:
try:
dataNew = c.recv(4024)
c.sendall(dataNew)
if not dataNew:
print('waiting or disconnected')
break
if dataNew:
print(dataNew, a)
except Exception as b:
print('error')
def mainLoop():
while True:
global c
global a
c, a = s.accept()
print('Connected by', a)
mainInput()
mainLoop()
Проблема в том, что ввод пустого сообщения нарушает работу программы.
1 ответ
Основная проблема здесь в том, что вы звоните input()
при условии, что вы получите что-то обратно. Но если пользователь просто нажимает Enter, эта функция возвращает пустую строку (input
полоски новой строки). Пустая строка содержит ноль символов. Если вы записываете ноль символов в сокет, ничего не отправляется (TCP является потоковым протоколом и не учитывает границы "сообщения", поэтому send
нулевые байты, по сути, запрещены (хотя, если известно, что соединение находится в закрытом или отключенном состоянии, исключение все равно можно сгенерировать)). Таким образом, клиент ничего не отправляет, а затем пытается прочитать отраженный ответ от сервера. Но сервер ничего не получил, поэтому сервер все еще ждет recv
и никогда не достигнет своего sendall
, Так что теперь клиент также ждет (навсегда) в recv
,
Другие проблемы в коде:
Если вы обнаружите ошибку в настройке сервера, вы должны выйти, а не просто распечатать сообщение и продолжить, поскольку последующие операции зависят от результатов предыдущих операций.
Аналогичным образом, если вы столкнулись с исключением на сервере, вы должны прервать цикл, а не продолжать, поскольку вы, как правило, просто получите исключение после исключения, если продолжите пытаться работать с сокетом в отключенном состоянии.
Если recv
возвращает пустую строку, это означает, что другая сторона закрылась (или shutdown
), поэтому вы должны немедленно выйти из цикла, а не пытаться sendall
в строке, так как (даже если строка пуста, как отмечено выше), это может генерировать исключение.