0

The Server receives String requests from the Client and replies with a String message to the Client.

I think the Server has to send the reply differently from how it is right now, so I think this line should be altered: c.sendall('Server: '+str.encode(reply))

Python Server:

# 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:
        # https://stackoverflow.com/questions/166506/finding-local-ip-addresses-using-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 Client Thread:

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());
        }
    }
}

The program gets stuck at String in = stdIn.readLine();

I can't figure out a way in which the java application is able to receive the Message from the server, even though the Java program is able to send messages to the server.

Thank you in advance

AJNeufeld
  • 8,526
  • 1
  • 25
  • 44
Arkanipro MA
  • 9
  • 1
  • 3
  • You have mixed up your send/recv protocols. When you send from Java, you print the string without any terminator, and “flush” the output stream. On the python side, `c.recv()` will return a message of any size up to 1024 bytes. There is no guarantee that you will get a complete message. You could get fewer bytes than were sent, and have to call recv again for the remainder, or you could get additional bytes from the next message, if messages are sent back-to-back. On the reverse side, you aren’t flushing, nor are you sending a new-line; readLine() is waiting for a character you never send – AJNeufeld Apr 29 '18 at 21:02
  • Fixed formatting and grammar a little bit. – Alpha Apr 30 '18 at 00:56

1 Answers1

0

If you want to communicate with a server using a "line-oriented" protocol (ie, each line sent terminated by \n, reading lines using readline type functions, you should create file objects for the socket in python, and simply use these sock_in and sock_out objects instead of the standard IO channels sys.stdin and sys.stdout in your input/output statements.

socket.makefile() is used to create the sock_in and sock_out file objects. Using encoding='utf-8' specifies the conversion between Python characters and the socket's byte stream.

c.sendall is not used at all. Instead we use print(..., file=sock_out) to transmit the text. flush=True should only be used only on the last output from the server in response to any single command; it may be used on every output statement, but will result in more overhead and lower performance.

Here is a Minimal, Complete, Verifiable example of such as server, in Python3.6. It simply echo's back whatever is sent to it, except for the exit and kill commands. You can test it without involving a Java client using a command like 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")

On the Java side, change ...

 out.print("Try");
 out.flush();

... to ...

 out.println("Try");
 out.flush();

... or the server will keep waiting for the \n character which terminates the line sent from the client.

Also, since we explicitly use utf-8 as the encoding on the python server, you should add the corresponding character encoding in your InputStreamReader and wrap socket.getOutputStream() in a OutputStreamWriter with the same encoding.

AJNeufeld
  • 8,526
  • 1
  • 25
  • 44