【问题标题】:Socket is being closed? (Android & Python)套接字正在关闭? (安卓和 Python)
【发布时间】:2018-11-02 18:30:04
【问题描述】:

我尝试在我的 Android 应用程序中使用 Sockets,但遇到了一个小问题。

我使用 python 创建服务器,一切正常。服务器收到来自安卓客户端的消息,但是客户端好像收不到响应。

这是我的服务器端:

import socket

HOST = '10.10.0.153'
PORT = 7800

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('socket created')

try:
    s.bind((HOST, PORT))
except socket.error as err:
    print('binding faild')
s.listen(10)


while 1:
    conn, addr = s.accept()
    print('Connect with ' + addr[0] + ':' + str(addr[1]))
    buf = conn.recv(1024)
    print(buf)
    data = "hello"
    conn.send(data.encode('utf-8'))
s.close()

这是客户端:

public class Sender extends AsyncTask<String, Void, Void> {

    private final String TAG = "Sender";

    Socket s;
    PrintWriter pw;

    @Override
    protected Void doInBackground(String... strings) {

    String message = strings[0];

    try {
        s = new Socket(GlobalVars.SERVER, GlobalVars.PORT);
        pw = new PrintWriter(s.getOutputStream());

        pw.write(message);
        pw.flush();

        BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String msg = in.readLine();
        System.out.println(msg);

        pw.close();
        s.close();
    } catch(IOException e) {
        e.printStackTrace();
    }
}
  • 编辑 - 我不再收到此错误。下去看看新问题 我得到的错误是一个 IOException,说套接字已关闭,但我从未关闭它。

错误:

W/System.err: java.net.SocketException: Socket is closed
                  at java.net.Socket.getInputStream(Socket.java:935)
W/System.err:     at net.traveler.liel.traveler.Server.Sender.doInBackground(Sender.java:34)
                  at net.traveler.liel.traveler.Server.Sender.doInBackground(Sender.java:14)
                  at android.os.AsyncTask$2.call(AsyncTask.java:333)
                  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
                  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
W/System.err:     at java.lang.Thread.run(Thread.java:764)
E/Sender: IOException 1

感谢您的帮助!

【问题讨论】:

    标签: java android python sockets


    【解决方案1】:

    尝试从您的代码中删除pw.close();。 也尝试删除这个:

      if(!s.isClosed()) {
            try {
                s.close();
            } catch (IOException e) {
                e.printStackTrace();
                Log.e(TAG, "IOException 2");
            }
        }
    

    【讨论】:

    • 如果我同时删除两者,我不会收到错误消息,但套接字在任何时候都没有关闭,所以我无法发出另一个请求...
    • 尝试只删除 pw.close();并尝试在不移除其他方法的情况下移除其他方法,看看哪个方法导致错误。
    • 如果我删除 pw.close();我无法发送另一个请求。同样适用于 s.close();如果我删除它,我将无法再提出请求。
    • 好,然后去掉isClosed()方法。
    • 我已经删除了 isClosed() 方法。我添加了一个调试,发现“String msg = in.readLine();”有一个错误,因为此行之后的所有内容都没有被执行。我在控制台中没有收到任何错误,所以这很奇怪。
    【解决方案2】:

    我向你推荐以下几点:

    使用 SocketIO 从 Python 连接到 Java。见here

    您还可以使用 Flask 构建 HTTP(S) 服务器并连接到您的 java 服务器 > here

    在生产环境中使用原始套接字从来都不是一个好主意,我更喜欢 Netty 用于 Java 应用程序和 Spring 用于 RESTful 服务。

    此外,您的代码正在主线程中运行,如果客户端断开连接,Python 服务器会自行中断。

    不要在生产中使用此代码!这是不安全的!

    您也可以用 Java 构建它:

    public class NetworkServer {
    
    public void run(String address, int port) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.childHandler(new PipelineInjector())
                    .group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 100)
                    .option(ChannelOption.SO_RCVBUF, 4096)
                    .option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(4096));
    
    
            ChannelFuture f = b.bind(address, port).sync();
            System.out.println("Network server succesfully bound to :" + address + ":" + port);
            try {
                f.channel().closeFuture().sync();
            } catch (Exception e) {
                System.out.println("Couldn't bind server to :" + address + ":" + port);
                System.exit(1);
            }
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    

    }

    还有客户:

    public class NetworkClient {
    
    public void run(String address, int port) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        try {
            Bootstrap b = new Bootstrap();
            b.childHandler(new PipelineInjector())
                    .group(bossGroup, workerGroup)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 100)
                    .option(ChannelOption.SO_RCVBUF, 4096)
                    .option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(4096));
    
    
            ChannelFuture f = b.connect(address, port).sync();
    
            try {
                f.channel().closeFuture().sync();
            } catch (Exception e) {
                System.exit(1);
            }
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        } }
    

    这个例子展示了一个 Netty 客户端和一个 Netty 服务器。 Netty 非常有用,而且效果很好。 Netty 可能有点困难,但效果很好。

    为了安全地使用 Netty,您需要使用 TLS/SSL 加密所有消息。 另外,您应该添加一个消息队列来将无法发送的消息排队。 做人脉的方法有很多,也许你对其中一种方法感到满意。

    【讨论】:

      【解决方案3】:

      在 Java 方面,您要求阅读“行”。一行必须以换行符 (docs) 结束。如果没有换行符,您的 Java 代码将坐在那里,阻塞在 readLine() 内,等待换行符到达。将您的 python 代码更改为:

      data = "hello\n"

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-03
        • 2011-06-29
        • 1970-01-01
        • 2018-10-11
        • 1970-01-01
        • 2015-09-05
        • 2018-07-27
        • 1970-01-01
        相关资源
        最近更新 更多