首页 文章

设置Socket Client始终监听数据

提问于
浏览
-2

我可以设置客户端 Socket 向服务器发送请求( sendData() 方法)并正确读取收到的消息( readData() 方法),但每次我使用 MOBILE_REQUEST 字符串通过这些代码向服务器发送请求时,我只收到消息:

@Override
protected Boolean doInBackground(String... params) {
    try {
        mSocket = new Socket(
                // PC Ip is 192.168.1.199 
                // It is the other device, Not be local host : 127.0.0.1
                Pas.pas.getPcIP(), 17001);

        DataOutputStream mDos = new DataOutputStream(mSocket.getOutputStream());

        String RESPONSE = null;
        String MOBILE_BLOCK = "MobileBlock#";

         // Converting collected data in byte array into String.
         RESPONSE = sendData(mDos, MOBILE_BLOCK);

         /**
           * The result response from PC app in here
           */
         // Log : response - #WindowsResp#192.168.1.199#
         Log.i("", "response '" + RESPONSE + "'");

        }

    } catch (SocketTimeoutException e) {
        IS_SOCKET_TIME_OUT = true;

        e.printStackTrace();
    } catch (ConnectException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

sendData() 方法 - 客户端将请求发送到服务器并等待获取响应数据 - 字符串数据 .

private String sendData(DataOutputStream mDos, String MOBILE_REQUEST) {
    try {
        // Log : MOBILE_REQUEST.getBytes() - [B@82f10f8
        mDos.write(MOBILE_REQUEST.getBytes());

        // todo I should set this sleep, bcs TCP has delay time, 
        // so i need set the delay time for client should receive data
        // otherwise, sometimes I did not receive anything
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // Log : #WindowsResp#192.168.1.199#
        return new String(readData(mSocket));
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

readData() 方法 - 从服务器收到数据后读取数据 .

public static byte[] readData(Socket mSocket) {
    /* Since data are accepted as byte, all of them will be collected in the
        following byte array which initialised with accepted data length. */
    DataInputStream mDis = null;
    try {
        mDis = new DataInputStream(mSocket.getInputStream());

        // Log : mDis.available() - 23
        byte[] data = new byte[mDis.available()];

        // Collecting data into byte array
        for (int i = 0; i < data.length; i++)
            data[i] = mDis.readByte();

        // Log : data - [B@30c044a4
        return data;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

我想要的是每次服务器通过单击按钮向我的套接字客户端发送消息,套接字客户端应该接收它 . 但在上面的代码中,它不是 .

请教我如何设置套接字客户端始终从服务器监听?

p / s:或者我需要设置 ServerSocket ?如果使用 ServerSocket 我不能使用相同的端口,对吧?因为当我首先打开 ServerSocket 进行侦听时(例如在端口17001),我无法使用客户端套接字通过端口17001发送请求,因为该端口已被使用 .

UPDATED

服务器(PC应用程序 - 笔记本电脑设备)发送到客户端(移动设备 - Android)的方式是通过Socket TCP,通过以下步骤:

1 - 客户端(Android设备)设置与服务器(PC应用程序)的TCP套接字连接(此连接永远不会关闭,直到在 onDestroy() 方法中退出应用程序) .

2 - 客户端向服务器发送请求,例如 MOBILE_REQUEST = "MobileID#MobileIP#"

3 - 服务器收到客户端的请求,它通过Socket连接回复客户端,实际上客户端正确接收了数据 . 恩 . "WindowsRep#WindowsIP"

这种方式对我不起作用,即使套接字TCP连接未关闭, getInputStream() 尚未关闭 . 在这种情况下 :

服务器通过Socket连接向客户端发送字符串数据,客户端正确接收数据 .

我想要的是每次“服务器通过Socket连接向客户端发送字符串数据,客户端正确接收数据” . 但就我而言,客户端只在向服务器发送请求后才接收数据 .

C# Server

服务器套接字

IPEndPoint ipe = new IPEndPoint("192.168.1.199", 17001);
svSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
svSocket.Bind(ipe);

服务器发送数据

string data_send = "#WBroad#" + "192.168.1.199" + "#";
byte[] byteData = Encoding.UTF8.GetBytes(data_send);
c.ClientSocket.Send(byteData);

1 回答

  • 0

    由于您尚未发布发送代码,因此无法确定您为何没有收到数据,但这里是对您发布的内容的快速评论:

    //            mSocket.setReuseAddress(true);
    

    你已经提出了这个问题,但现在调用这个方法毫无意义 . 您必须将套接字构造为 new Socket() ,没有参数,然后调用此方法,然后调用 connect() . 由于您没有提供要重复使用的源端口或IP地址,因此它仍然毫无意义 .

    byte[] data = new byte[mDis.available()];
    

    这完全是对 available() 的误用 . 它不提供消息长度 . 见Javadoc . 没有理由相信在这一点上已经到达的任何数据(如果有的话)是完整的消息,或者只有一条消息 . 如果你想要消息,你将无法从TCP获得任何帮助:你必须自己实现它们 . 由于您的协议似乎是基于文本的,我建议您只使用行和 readLine() ,使用 BufferedReaderBufferedWriter 而不是 DataInput/OutputStreams . 并在套接字的生命周期中构建一次,而不是每个应用程序消息一次,否则您将丢失数据 .

    // Collecting data into byte array
            for (int i = 0; i < data.length; i++)
                data[i] = mDis.readByte();
    

    huge 这个问题是它不会阻塞,因为大部分时间 available() 都是零,所以除了返回一个空的 byte[] 数组之外,这个方法什么都不做 .

    在任何情况下,这完全等同于 mDis.readFully(data); ,效率只有几倍,但你不应该这样做:见上文 .

    return data;    
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    

    这是不好的做法 . 你应该让这个方法抛出 IOException 并让调用者处理它 .

    mDos.write(MOBILE_REQUEST.getBytes());
    

    往上看 . 这应包括行终止符,长度字前缀或其他一些分隔消息的方法 .

    try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    

    这种睡眠完全是浪费时间 . 和空间 . 去掉它 . 睡在网络代码中只是货物编程 .

    return new String(readData(mSocket));
    

    这将抛出 NullPointerException 如果 readData() 返回 null ,如果有 IOException 它会这样做,这是让该方法传播该异常而不是在内部捕获并返回null的另一个原因 .

    private boolean splitData(int mobile_send_request_case, String DATA) {
    

    此方法与问题完全无关,因此不应发布 .

    或者我需要设置ServerSocket?

    不,你为什么这么认为?

    如果使用ServerSocket我不能使用相同的端口,对吧?

    错误 .

    因为当我首先打开ServerSocket进行监听时(例如在端口17001),我无法使用客户端套接字通过端口17001发送请求,因为该端口已被使用 .

    又错了 . 事实并非如此 .

    如上所述,当您不发布所有相关代码时,无法进一步帮助您,但是已经有足够的错误,你真的需要重新开始 .

相关问题