简体   繁体   English

为什么我的Android客户端无法从Winsock C ++服务器接收字符串消息?

[英]Why my android client cannot receive string message from winsock c++ server?

I am trying to build an android app that communicates with a c++ server running on windows using TCP sockets. 我正在尝试构建一个与使用TCP套接字与Windows上运行的c ++服务器通信的android应用。 I successfully sent a string from the app to the server but I cannot do the other way around. 我已成功将字符串从应用程序发送到服务器,但我无法进行其他操作。 Please help me because I have been trying with this issue for a while now. 请帮助我,因为我已经尝试了一段时间了。

Android Client: Android客户端:

String mystr="Hello World...";
char[] buffin=new char[128];
String input =null;
Integer count = 0;
class TextRcv extends AsyncTask<Void, Void, Integer>
{

    @Override
    protected Integer doInBackground(Void... params) {

        //Sending a string (WORKING)
        Socket clientSocket = null;
        try {
            clientSocket= new Socket("192.168.1.5",8889);
            DataOutputStream oos= new DataOutputStream(clientSocket.getOutputStream());
            oos.writeBytes(mystr);
            //oos.writeBytes(String.valueOf(mystr.length()));//write the length of the string first
            //byte[] bufferout=mystr.getBytes();
            //oos.write(bufferout, 0, bufferout.length);
            oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //Recieving a String (Not working)
        try {
            BufferedReader in = null;
            if (clientSocket != null)
            {
                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            }
            else
            {
                Log.e("samer ","CLIENTSOCKET NULL");
            }

            if (in != null)
            {
                count=in.read(buffin);
            }
            else
            {
                Log.e("samer ","BUFFERREADER NULL");
            }

            if(count>0)
            {
                input=new String(buffin,0,count);
            }
            if (clientSocket != null) {
                clientSocket.close();
            }

        } catch (IOException e) {
            Log.i("samer count: ",String.valueOf(count));//RETURNS 0 !!
            Log.i("buff samer: ", String.valueOf(buffin));//Returns garbage
            e.printStackTrace();
        }
        return count;
    }

    @Override
    protected void onPostExecute(Integer count) {
        super.onPostExecute(count);

        Toast toast=Toast.makeText(getApplicationContext(),String.valueOf(count),Toast.LENGTH_LONG);
        toast.show();
    }
}

The 'count' always returns 0 despite the fact that on the windows c++ server side it says that it has successfully sent the 25 bytes. 尽管在Windows c ++服务器端它已成功发送了25个字节,但“ count”始终返回0。

C++ Winsock Server: C ++ Winsock服务器:

int  main(int argc, const char *argv[])
{
    WSADATA wsaData;
    int iResult;
    SOCKET ListenSocket = INVALID_SOCKET;
    SOCKET ClientSocket = INVALID_SOCKET;

    struct addrinfo *result = NULL;
    struct addrinfo hints;
    int valread;
    int iSendResult;
    char * recvbuf;
    char *recvstr;
    int recvbuflen = DEFAULT_BUFLEN;
    recvbuf = (char*)malloc((recvbuflen + 1) * sizeof(char));
    recvstr = (char*)malloc((recvbuflen + 1) * sizeof(char));
    char* AndroidID;
    char *sendbuf = "Client: sending data test";

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);

        return 1;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    // Resolve the server address and port
    iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();

        return 1;
    }

    // Create a SOCKET for connecting to server
    ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (ListenSocket == INVALID_SOCKET) {
        printf("socket failed with error: %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();

        return 1;
    }

    // Setup the TCP listening socket
    iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        printf("bind failed with error: %d\n", WSAGetLastError());
        freeaddrinfo(result);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    freeaddrinfo(result);

    iResult = listen(ListenSocket, SOMAXCONN);
    if (iResult == SOCKET_ERROR) {
        printf("listen failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();

        return 1;
    }

    // Accept a client socket
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();

        return 1;
    }

    if (ClientSocket != INVALID_SOCKET)
    {
        cout << "Start Receving" << endl;

        //------Start Receiving
        //-----------------------------------
        int lengthofrecv=recv(ClientSocket, recvbuf, recvbuflen, 0);
        recvbuf[lengthofrecv] = '\0';//append \0 to use with printf()
        AndroidID = recvbuf;
        printf("AndroidID - %s \n", recvbuf);
        cout << " \n Done ";

        //---Start Sending to android
        //-----------------------------------------
        iResult = send(ClientSocket, sendbuf, (int)strlen(sendbuf), 0);
        if (iResult == SOCKET_ERROR) 
        {
            wprintf(L"send failed with error: %d\n", WSAGetLastError());
            closesocket(ClientSocket);
            WSACleanup();
            return 1;
        }
        printf("Bytes Sent: %d\n", iResult);

        cout << WSAGetLastError() << endl;
    }

    // shutdown the connection since we're done
    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }

    //cleanup
    closesocket(ClientSocket);
    WSACleanup();

    return 0;
}

Server console output: 服务器控制台输出:

Start Receving 开始收录

AndroidID - Hello World... AndroidID-Hello World ...

Done Bytes Sent: 25 发送的完成字节数:25

0 0

Press any key to continue . 按任意键继续 。 . .

The problem is that you are calling oos.close() after sending the initial string to the server. 问题是您将初始字符串发送到服务器后正在调用oos.close()

DataOutputStream extends FilterOutputStream , and the behavior of its close() method is documented: DataOutputStream扩展了FilterOutputStream ,并记录了其close()方法的行为:

FilterOutputStream.close() FilterOutputStream.close()

The close method of FilterOutputStream calls its flush method, and then calls the close method of its underlying output stream . FilterOutputStream的close方法调用其flush方法,然后调用其基础输出流的close方法

In this case, the "underlying output stream" is the socket's outputStream, and its close() behavior is also documented: 在这种情况下,“底层输出流”是套接字的outputStream,并且其close()行为也已记录在案:

Socket.getOutputStream() Socket.getOutputStream()

Closing the returned OutputStream will close the associated socket . 关闭返回的OutputStream将关闭关联的套接字

Socket.close() Socket.close()

Closes this socket. 关闭此套接字。

Any thread currently blocked in an I/O operation upon this socket will throw a SocketException. 当前在此套接字上的I / O操作中阻塞的任何线程都将引发SocketException。

Once a socket has been closed, it is not available for further networking use (ie can't be reconnected or rebound). 插座一旦关闭,便无法再用于网络连接 (即无法重新连接或反弹)。 A new socket needs to be created. 需要创建一个新的套接字。

Closing this socket will also close the socket's InputStream and OutputStream. 关闭此套接字还将关闭套接字的InputStream和OutputStream。

If this socket has an associated channel then the channel is closed as well. 如果此套接字具有关联的通道,则该通道也将关闭。

So, your client is closing the socket connection before it can read the server's reply string. 因此,您的客户端要先关闭套接字连接,然后才能读取服务器的回复字符串。 You need to remove that call to oos.close() so yo keep the connection open until you are done reading. 您需要删除对oos.close()调用,这样oos.close()保持连接打开,直到完成阅读为止。

On the server side, simply due to timing, your code may be able to call send() and put the reply string into the socket's outbound buffer before the socket detects the disconnect. 在服务器端,仅由于时间限制,您的代码就可以在套接字检测到断开连接之前,调用send()并将回复字符串放入套接字的出站缓冲区。 The buffer is not actually transmitted by send() itself, it is queued to the OS kernel, which will transmit the data in the background. 该缓冲区实际上不是由send()本身实际传输的,而是排队到OS内核,后者将在后台传输数据。 So send() will return success instead of failure if the reply string is buffered before the disconnect is detected. 因此,如果在检测到断开连接之前缓冲了回复字符串,则send()将返回成功而不是失败。

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

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