Если вы хотите обмениваться данными с сервером, используя «линейно-ориентированный» протокол (т. Е. Каждая отправляемая строка заканчивается \n
, читая строки с использованием функций типа readline
, вы должны создать file
объекты для сокета в Python, и просто используйте эти sock_in
и sock_out
объекты вместо стандартных каналов ввода-вывода sys.stdin
и sys.stdout
в ваших операторах ввода / вывода.
socket.makefile()
используется для создания файловых объектов sock_in
и sock_out
. Использование encoding='utf-8'
указывает преобразование между символами Python и потоком байтов сокета.
c.sendall
не используется вообще. Вместо этого мы используем print(..., file=sock_out)
для передачи текста. flush=True
должен использоваться только на последнем выходе сервера в ответ на любую отдельную команду; он может использоваться в каждом операторе вывода, но это приведет к увеличению издержек и снижению производительности.
Вот минимальный, полный, проверяемый пример сервера, в Python3.6. Он просто возвращает все, что ему отправлено, за исключением команд exit
и kill
. Вы можете протестировать его без участия клиента Java, используя команду типа telnet localhost 8889
.
server.py:
import socket
class ClientKill(Exception):
pass
def _serviceClient(sock_in, sock_out):
for line in sock_in:
line = line.rstrip('\n')
if line == 'exit':
break
if line == 'kill':
raise ClientKill()
print(line, file=sock_out, flush=True) # Echo back
def serviceClient(client, addr):
with client, client.makefile('r', encoding='utf-8', newline='\n') as sock_in, \
client.makefile('w', encoding='utf-8', newline='\n') as sock_out:
_serviceClient(sock_in, sock_out)
port = 8889
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as listener:
listener.bind(('localhost', port))
listener.listen(0)
try:
while True:
client, addr = listener.accept()
serviceClient(client, addr)
except ClientKill:
print("Server killed by remote client")
На стороне Java измените ...
out.print("Try");
out.flush();
... до ...
out.println("Try");
out.flush();
... или сервер продолжит ждать символа \n
, который завершает строку, отправленную клиентом.
Кроме того, поскольку мы явно используем utf-8
в качестве кодировки на сервере Python, вы должны добавить соответствующую кодировку символов в ваш InputStreamReader
и обернуть socket.getOutputStream()
в OutputStreamWriter
с той же кодировкой.