Приложение 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 в строке, так как (даже если строка пуста, как отмечено выше), это может генерировать исключение.

Другие вопросы по тегам