Сокет закрывается? (Android & Python) - PullRequest
0 голосов
/ 02 ноября 2018

Я попытался использовать Sockets в своем приложении для Android, и столкнулся с небольшой проблемой.

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

Это мой server.py:

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()));
        System.out.println("1");
        //String msg = in.readLine();
        System.out.println("2");
        //System.out.println(msg);
        System.out.println("3");

        pw.close();
        s.close();
    } catch(IOException e) {
        e.printStackTrace();
        Log.e(TAG, "IOException 1");
    }
}
  • Редактировать - я больше не получаю эту ошибку. Спуститесь вниз, чтобы увидеть новую проблему Ошибка, которую я получаю, это 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

Новая проблема: когда я пытаюсь получить ответ (in.readLine ()), он просто перестает работать, как будто сервер ничего не отправляет обратно.

Ответы [ 3 ]

0 голосов
/ 02 ноября 2018

Я рекомендую вам следующие вещи:

Используйте SocketIO для подключения из Python к Java. Смотри здесь

Вы также можете создать HTTP (S) сервер с Flask и подключиться к вашему Java серверу> здесь

Использование сырых сокетов никогда не было хорошей идеей для работы, я предпочитаю 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 необходимо зашифровать все сообщения с помощью TLS / SSL . Кроме того, вы должны добавить очередь сообщений в очередь сообщений, которые не могли быть отправлены. Есть много способов создания сетей, возможно, вы удовлетворены одним из этих методов.

0 голосов
/ 03 ноября 2018

На стороне Java вы просите прочитать "строку". Строка должна заканчиваться символом перевода строки ( docs ). Без перевода строки ваш Java-код будет просто сидеть там, блокируясь внутри readLine(), ожидая поступления перевода строки. Измените свой код Python на этот:

data = "hello\n"

0 голосов
/ 02 ноября 2018

Попробуйте удалить pw.close(); из вашего кода. Также попробуйте удалить это:

  if(!s.isClosed()) {
        try {
            s.close();
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, "IOException 2");
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...