简体   繁体   English

套接字Python(服务器)到Java(客户端)的连接Java无法从主机接收数据

[英]Socket Python(Server) to Java(Client) connection Java is not able to receive data from host

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)) 我认为服务器必须以不同于现在的方式发送答复,因此我认为这一行应该更改: c.sendall('Server: '+str.encode(reply))

Python Server: 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:
        # 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: 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());
        }
    }
}

The program gets stuck at String in = stdIn.readLine(); 程序卡String in = stdIn.readLine();中的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. 我无法弄清楚Java应用程序能够从服务器接收消息的方法,即使Java程序能够将消息发送到服务器也是如此。

Thank you in advance 先感谢您

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. 如果要使用“面向行的”协议与服务器通信(即,每行以\\n终止,使用readline类型的函数读取行,则应在python中为套接字创建file对象,只需使用这些sock_insock_out对象,而不是输入/输出语句中的标准IO通道sys.stdinsys.stdout

socket.makefile() is used to create the sock_in and sock_out file objects. socket.makefile()用于创建sock_insock_out文件对象。 Using encoding='utf-8' specifies the conversion between Python characters and the socket's byte stream. 使用encoding='utf-8'指定在Python字符和套接字的字节流之间进行转换。

c.sendall is not used at all. c.sendall根本不使用。 Instead we use print(..., file=sock_out) to transmit the text. 相反,我们使用print(..., file=sock_out)传输文本。 flush=True should only be used only on the last output from the server in response to any single command; flush=True仅应用于响应任何单个命令的服务器的最后输出; 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. 这是Python3.6中服务器的最小,完整,可验证示例。 It simply echo's back whatever is sent to it, except for the exit and kill commands. 它简单地回显返回的内容,除了exitkill命令。 You can test it without involving a Java client using a command like telnet localhost 8889 . 您可以使用telnet localhost 8889类的命令在不涉及Java客户端的情况下对其进行测试。

server.py: 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 ... 在Java方面,更改...

 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. ...否则服务器将继续等待\\n字符,该字符将终止从客户端发送的行。

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. 另外,由于我们在Python服务器上显式使用utf-8作为编码,因此您应在InputStreamReader添加相应的字符编码,并将socket.getOutputStream()包装在具有相同编码的OutputStreamWriter

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM