Socket c++: recv function returns -1

4.8k views Asked by At

I'm trying to code a simple android client communicating with a windows server. I'm using sockets to achieve that and up to now, I was testing everything with a Linux machine (android client and linux server). So far, everything was working. Now i'm trying to set it up on windows (the server) and I have of course noticed that I had to change my code a little (if not just the include ^^'). Anyway, my problem is that my recv functions returns -1 while it should read something but it doesn't for some reason.

Below is how I use my recv function (EDIT: the whole server code now):

int tcp_server::start_listening()
{

    WORD wVersionRequested;
    WSADATA wsaData;
    int wsaerr;
    wVersionRequested = MAKEWORD(2, 2);
    wsaerr = WSAStartup(wVersionRequested, &wsaData);
    if (wsaerr != 0)
    {
        printf("Server: The Winsock dll not found!\n");
        WSACleanup();
        return 0;
    }

   else
    {
        printf("Server: The Winsock2 dll found \n");
    }

    sSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if(sSock == INVALID_SOCKET)
    {
        printf("Server: Error initializing socket!n");
        WSACleanup();
        return 0;
    }


    sockaddr_in service,client ;
    service.sin_family = AF_INET;
    service.sin_port = htons(port);
    service.sin_addr.s_addr = INADDR_ANY;


   if(bind(sSock,(SOCKADDR*)&service,sizeof(service))==SOCKET_ERROR)
   {
       printf("Server: Error binding socket to portn");
       WSACleanup();
       return 0;
   }

   /* wait for incoming connections */
   if(listen(sSock,10)==SOCKET_ERROR)
       printf("listen(): Error listening on socket %d\n", WSAGetLastError());
   else
   {
      printf("Server: Waiting for connections...\n");
   }

   /* accept connections */
   AcceptSocket;
   printf("Server: Waiting for a client to connect...\n");
   AcceptSocket = accept(sSock, NULL, NULL);
   if (AcceptSocket == INVALID_SOCKET) {
       wprintf(L"accept failed with error: %ld\n", WSAGetLastError());
       closesocket(sSock);
       WSACleanup();
       return 1;
   } else {
       wprintf(L"Client connected.\n");
       acceptConns();
   }

   closesocket(sSock);
   return 0;
}
int tcp_server::acceptConns()
{
    sockaddr_in from;
    bool infinite = true ;
    int fromlen=sizeof(from);
    int readsize;
    char* message;
    char* clientmessage = "\0";
    string smatrix ;
    int ind ;
    string tok;
    int i = 0 ;
    int bytesSent ;

    float matrix[16] ;
    while( (readsize = recv(AcceptSocket, clientmessage, 2000, 0))!= 0 ){
        message = "ack";
        cout << "Writing ACK" << endl ;
        smatrix = clientmessage ;
        std::stringstream ss(smatrix);

        cout << smatrix << endl ;
        while(getline(ss, tok, ',') && i < 16 ){
            matrix[i] = static_cast<float>(::atof(tok.c_str()));
            i++ ;
        }
        i = 0 ;
        Sleep(1000);
    }
    if(readsize == 0 ){
        cerr << "client disconnected" << endl ;
    }
    cout << "Socket closed" << endl ;
    closesocket(sSock);
    WSACleanup();
}

As for my android code: here it is:

 while(closeConnection == false) {
        if (connected == true && matrixupdated == true && this.hasMatrixChanged()){
            try {
                //= new BufferedReader(new InputStreamReader(java.lang.System.in));
                DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
                String sentence = this.getStringFromMatrix();
                outToServer.writeBytes(sentence + "\n");
                outToServer.flush();
                inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                System.arraycopy(matrix, 0, previousMatrix, 0, 16);
                inFromServer.read(serverMsg);
                if(serverMsg.equals("ack") == true){
                    this.serverHasInput = false ;
                    Log.e("ACK", "ACK");
                    inFromServer.read(serverMsg);       //Wait for the "ok" message from server
                    if(serverMsg.equals("ok") == false){
                        Log.e("ERROR IN COM W/ SERV"," DID NOT RECEIVE OK");
                    }
                }
                else{
                    this.serverHasInput = true ;
                }
                //Log.d("SERVERMSG", "DONE WAITING");

            }catch (Exception e) {
                Log.e("ClientActivity", "S: Error", e);
            }
            this.matrixupdated = false ;
        }

    }
    try {
        outToServer.flush();
        outToServer.close();
        inFromServer.close();
        clientSocket.close();
    }

Finally the output I get in the console is unfortunately

client disconnected

I'm guessing this is probably some really dumb stuff, but i've been trying to see on MS website and the documentation of recv why it would give me -1 but I can't get my hands on a explanation.

Thanks in advance for the help provided :).

2

There are 2 answers

12
Nikolai Fetissov On BEST ANSWER

Many errors in the C++ code - like if (bytesSent = 0), which is an assignment with result cast to boolean, so always returning false. You don't pay attention to number of bytes read from a TCP socket, assuming that you receive one complete message as you sent it - this is wrong since you might be reading a partial message, more then one message, or anything in between - it is a raw byte stream.

Check for -1 returned from system calls explicitly, and then examine the value of errno(3), with say, strerror(3) function to figure out what went wrong.

Edit 0:

You are trying to use the listening socket sSock for data transfer - wrong - it is only there for accepting client connection requests. Use AcceptedSocket, the one returned from accept(). It is the connection to the client.

5
Martin James On

The client socket that you should be reading/writing to is the 'AcceptSocket' that is returned by the Accept() call, Not the 'sSock' server socket!

Either move the declaration of AcceptSocket to a member var, pass it to 'acceptConns();' as a parameter or start a thread to run acceptConns, passing the AcceptSocket as the void* parameter to pthread_create, (or whatever).

I think that both Remy and I strongly suspected that this was your problem even before you posted the Accept code:)

Ohwait - Nikloai's edit got in first - upvote him!