Соединение сокета Python (сервер) с Java (клиент) Java не может получать данные с хоста - PullRequest
0 голосов
/ 29 апреля 2018

Сервер получает строковые запросы от клиента и отвечает клиентом строковым сообщением.

Я думаю, что Сервер должен отправить ответ не так, как сейчас, поэтому я думаю, что эту строку следует изменить: c.sendall('Server: '+str.encode(reply))

Сервер Python:

# This Python file uses the following encoding: utf-8
import socket

def setupServer(port):
    serv=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print("socket ist da")
    try:
        # /120803/poisk-lokalnyh-ip-adresov-s-ispolzovaniem-pythons-stdlib
        host=socket.gethostbyname(socket.gethostname())
        print('Host ip: '+host)
        serv.bind((host, port))
    except socket.error as msg:
        print(msg)
    print("socket bind fertig")
    return serv

def setupConnection(s):
    # Erlaubt 1 Verbindung gleichzeitig
    s.listen(1)
    connection, address=s.accept()
    print("Verbunden zu: "+address[0]+":"+str(address[1]))
    return connection


def gET():
    reply='GET ausgefuehrt'
    return reply

def rEPEAT(te):
    reply=te[1]
    return reply

def dataTransfer(c,s):
    # sendet und erhält Daten bis es stoppen soll
    while True:
        # Daten erhalten
        data=c.recv(1024)#daten erhalten 1024 Buffer size
        data=data.decode('utf-8')#nötig?
        # Teilt die Datei in Befehl/Command und data auf
        dataMessage=data.split(' ',1)
        command=dataMessage[0]
        if command=='GET'or command=='get':
            reply=str(gET())
        elif command=='REPEAT'or command=='repeat':
            reply=str(rEPEAT(dataMessage))
        elif command=='EXIT'or command=='exit':
            print("Er ist geganngen")
            break
        elif command=='KILL'or command=='kill':
            print("Server wird geschlossen!")
            s.close()
            break
        else:
            print("was?")
            reply="Nicht Vorhandener Befehl"
        # NAchricht senden
        c.sendall('Server: '+str.encode(reply))
        print(reply)
        print('Klint: '+data)
        print("Daten wurden geschickt")
    c.close()

def main():
    #print("hello")
    #host='192.168.1.120'
    #host='192.168.2.110'
    #print('Host ip: '+str(host))
    port=8999
    print('Port: '+str(port))
    s=setupServer(port)


    while True:
        try:
            conn=setupConnection(s)
            dataTransfer(conn,s)
        except:
            break

if __name__=="__main__":
    main()

Поток клиента Java:

public class SentThread extends Thread {

    Socket socket;
    Context cmain;
    //boolean stop=false;
    SentThread(Socket s,Context c) {
        socket = s;
        cmain=c;
    }

    @Override
    public void run() {
        Log.i("Roman", "run->");

        socket=new Socket();
        try{
        socket.connect(new InetSocketAddress("192.168.2.110", 8999),5000);
        }catch (Exception e) {
            Log.e("Roman", e.toString());
            Toast.makeText(cmain, e.toString(), Toast.LENGTH_SHORT).show();

        }


        try {
            BufferedReader stdIn = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            while (true) {
                out.print("Try");
                out.flush();
                System.out.println("Message sent");
                System.out.println("Trying to read...");
                String in = stdIn.readLine();
                System.out.println(in);
            }
        } catch (Exception e) {
            // TODO: handle exception
            Log.e("Roman", e.toString());
        }
    }
}

Программа застревает на String in = stdIn.readLine();

Я не могу понять, каким образом Java-приложение может получать Сообщение от сервера, даже если Java-программа может отправлять сообщения на сервер.

Заранее спасибо

1 Ответ

0 голосов
/ 30 апреля 2018

Если вы хотите обмениваться данными с сервером, используя «линейно-ориентированный» протокол (т. Е. Каждая отправляемая строка заканчивается \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 с той же кодировкой.

...