开发者

Problem in accepting connection from client (socket programming) in Visual C++

开发者 https://www.devze.com 2023-01-21 00:02 出处:网络
I have written a simple single threaded client server application in Visual C++. When I run my server I wait for some time that it accepts some request from the client.

I have written a simple single threaded client server application in Visual C++. When I run my server I wait for some time that it accepts some request from the client.

When I connect the client to the server. The log message on the client reports 14 bytes are send and there is no message on the server. I have written a print statement to print whatever is accepted by the server on the console, but the server doesn't print anything.

It seems to me like the client has connected to some other server.

The client and server code is below.

Server code

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <conio.h>

#define DEFAULT_PORT        "27015"
#define DEFAULT_BUFLEN        512
#pragma comment(lib, "Ws2_32.lib")

int main() {
    WSADATA wsdata;
    int result = WSAStartup(MAKEWORD(2,2),&wsdata);
    if (result != 0){
        printf("%s","Unable to initilize windows socket\n");
        getch();
        return 1;
    }

    struct addrinfo *addrResult = NULL,hints;
    ZeroMemory(&hints, sizeof (hints));

    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    开发者_StackOverflow社区hints.ai_flags = AI_PASSIVE;

    result = getaddrinfo(NULL,DEFAULT_PORT,&hints,&addrResult);
    if (result != 0){
        printf("%s","Error in getaddrInfo");
        getch();
        return 1;
    }
    SOCKET listenSocket = INVALID_SOCKET;
    listenSocket = socket(addrResult->ai_family,addrResult->ai_socktype,addrResult->ai_protocol);

    if (listenSocket == INVALID_SOCKET){
        printf("%s","Error in creating socket object\n");
        getch();
        closesocket(listenSocket);
        WSACleanup();
        return 1;
    }

    sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = inet_addr("127.0.0.1");
    service.sin_port = htons(27015);

    if (bind(listenSocket,addrResult->ai_addr,
        (int)addrResult->ai_addrlen) == SOCKET_ERROR){
    //if(bind(listenSocket,(SOCKADDR*) &service,
    //    sizeof(service)) == SOCKET_ERROR){

        printf("bind failed: %d\n", WSAGetLastError());
        freeaddrinfo(addrResult);
        closesocket(listenSocket);
        WSACleanup();
        getch();
        return 1;
    }
    freeaddrinfo(addrResult);
    if (listen(listenSocket,SOMAXCONN) == SOCKET_ERROR){
        printf("%s","Error in listening socket");
        getch();
        closesocket(listenSocket);
        WSACleanup();
    }
    SOCKET clientSocket = INVALID_SOCKET;
    clientSocket = accept((listenSocket,NULL,NULL);
    if (clientSocket ==  INVALID_SOCKET){
        closesocket(listenSocket);
        WSACleanup();
    }

    char recvbuf[DEFAULT_BUFLEN];
    int iRecvResult, iSendResult;
    int recvbuflen = DEFAULT_BUFLEN;

    do{
        iRecvResult = 0;
        iSendResult = 0;
        iRecvResult = recv(clientSocket,recvbuf,recvbuflen,0);
        if (iRecvResult > 0){
            printf("Bytes received: %d\n", iRecvResult);
            getch();
            // Echo the buffer back to the sender
            iSendResult = send(clientSocket, recvbuf, iRecvResult, 0);
            if (iSendResult == SOCKET_ERROR) {
                printf("send failed: %d\n", WSAGetLastError());
                closesocket(clientSocket);
                WSACleanup();
                return 1;
            }
            printf("Bytes sent: %d\n", iSendResult);
        }
        else if (iRecvResult == 0){
            printf("Connection closing...\n");
        }
        else{
            printf("recv failed: %d\n", WSAGetLastError());
            closesocket(clientSocket);
            WSACleanup();
            return 1;
        }
    }while(iRecvResult > 0);
  getch();
  return 0;
}

Client code

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <conio.h>

#define DEFAULT_PORT        "27015"
#define DEFAULT_BUFLEN        512
#pragma comment(lib, "Ws2_32.lib")

int main(){
    WSADATA wsdata;
    WSAStartup(MAKEWORD(2,2),&wsdata);
    struct addrinfo *addrResult = NULL,hints;
    ZeroMemory(&hints, sizeof (hints));
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_family = AF_UNSPEC;
    int result = 0;
    if (getaddrinfo("127.0.0.1",DEFAULT_PORT,
        &hints,&addrResult)){
            printf("%s","Error in getaddrInfo\n");
            WSACleanup();
            getch();
            return 1;
    }
    SOCKET connectingSocket = INVALID_SOCKET;
    connectingSocket = socket(addrResult->ai_family,addrResult->ai_socktype,
        addrResult->ai_protocol);
    if (connectingSocket == INVALID_SOCKET){
        printf("%s","Error in creating socket\n");
        freeaddrinfo(addrResult);
        WSACleanup();
        getch();
        return 1;
    }

    if (connect(connectingSocket,addrResult->ai_addr, (int)addrResult->ai_addrlen) != 0){
        closesocket(connectingSocket);
        connectingSocket = INVALID_SOCKET;
        WSACleanup();

    }
    freeaddrinfo(addrResult);

    int recvbuflen = DEFAULT_BUFLEN;
    char *sendbuf = "this is a test";
    char recvbuf[DEFAULT_BUFLEN];

    int iResult;

    // Send an initial buffer
    iResult = send(connectingSocket, sendbuf, (int) strlen(sendbuf), 0);
    if (iResult == SOCKET_ERROR) {
        printf("send failed: %d\n", WSAGetLastError());
        closesocket(connectingSocket);
        WSACleanup();
        return 1;
    }

    printf("Bytes Sent: %ld\n", iResult);

    // shutdown the connection for sending since no more data will be sent
    // the client can still use the connectingSocket for receiving data
    iResult = shutdown(connectingSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed: %d\n", WSAGetLastError());
        closesocket(connectingSocket);
        WSACleanup();
        return 1;
    }

    // Receive data until the server closes the connection
    do {
        iResult = recv(connectingSocket, recvbuf, recvbuflen, 0);
        if (iResult > 0)
            printf("Bytes received: %d\n", iResult);
        else if (iResult == 0)
            printf("Connection closed\n");
        else
            printf("recv failed: %d\n", WSAGetLastError());
    } while (iResult > 0);

    getch();
    return 0;
}


Hmm...after fixing the obvious syntax error (the un-matched open-parenthesis in clientSocket = accept((listenSocket,NULL,NULL);), it seems to work reasonably well for me. On the server I get:

Bytes received: 14
Bytes sent: 14
Connection closing...

and on the client:

Bytes Sent: 14
Bytes received: 14
recv failed: 10054

So, the client sends 14 bytes to the server, (you press enter), the server echoes those 14 bytes back to the client, (you press enter again), and the server closes the connection. The client reads the 14 bytes, then further reading fails when the connection is closed.

Edit: I ran the code by opening two Windows SDK command prompt windows, running server in one and client in the other -- nothing particularly exciting or unusual about either one.


You can confirm what is happening in your server code when the client tries to send by enhancing the diagnostics. More output at important times (e.g. successful connect(), accept(), close(), ALL socket errors, an optional send/recv traffic log file maybe) would likely quickly point the way to a solution. Make sure you check for and output any errors on ALL socket API calls.

You can check for other systems listening on your target port/address using netstat.

I can't see anything obvious wrong fwiw.


I'd suggest you to do the following:

  • Remove all getch() from code for the sake of experiment
  • Make sure that neither your tcp server nor tcp client apps are runnung
  • Remove all rules for your apps in windows firewall settings
  • run the following in CMD shell - you'll need to make GREP available:

    netstat -a -b | grep -e "27015" --after=1

If output of this command is not empty - you'll see the name of an application which is the source of the problem. Otherwise, try reproducing your problem by running the server and then - the client. Monitor the state of the server by the netstat command as above (or by tcpview program). It's interesting what the results would be.

Offtopic note: your disconnect sequence is incomplete. Google for graceful disconnect. Usually it looks like this:

[client] emit shutdown (sd_send) and wait for remaining data from server

[server] if recv()==0 then { send(remaining data); emit shutdown(sd_send); closesocket }

[client] receive remaining data; if recv()==0 then closesocket


In the client you are shutting down the connection for send:

// shutdown the connection for sending since no more data will be sent
// the client can still use the connectingSocket for receiving data
iResult = shutdown(connectingSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
    printf("shutdown failed: %d\n", WSAGetLastError());
    closesocket(connectingSocket);
    WSACleanup();
    return 1;
}

The server detects the disconnection (recv return 0) and finalize without shutting down the connection on its side, that is the reason why you are receiving the error 100054.

0

精彩评论

暂无评论...
验证码 换一张
取 消