matl
matl

Reputation: 135

TCP/IP server in C++ is not waiting for client

I found some code in the internet with some basics about creating an TCP/IP server in C++. I took this code, added some libraries and some lines of code. The result is, that I am able to compile and run the code/server in Qt Creator on Windows as a console program. Nevertheless I am not able to connect to the server because it just runs through the code without waiting and accepting a connection from an TCP client.

This is the code: EDIT: Code is updated and it's now working. Test against == -1 is the solution.

#define PORT 2000
#define MAX_QUEUE 5
#define BUF_SIZE 1024

int main(int argc, char* const argv[])
{
cout << "Hello World!" << endl;    
        WSADATA wsaData;
int wsaret = WSAStartup(MAKEWORD( 4, 4 ), &wsaData);
cout << "wsaret: " << wsaret << endl;

cout << "Start TCP/IP Server" << endl;

/* file descriptors for sockets */
SOCKET sock_1, sock_2;  //switched from in to SOCKET //unsigned int sock_1, sock_2;
int rec_value, length;
char buf[BUF_SIZE];

//struct sockaddr_in server;
struct sockaddr_in server;

/* create stream socket in internet domain*/
sock_1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//if(sock_1 < 0)
if(sock_1 == -1)
{
    cout << "socket: " << WSAGetLastError() << endl; //instead of //cout << "socket: " << strerror(errno) << endl; //cout << "socket wsaret: " << wsaret << endl;
    exit(1);
}

/* build address in internet domain */
server.sin_family = AF_INET;

/* everyone is allowed to connet to server */
server.sin_addr.s_addr = INADDR_ANY; //inet_addr("192.168.145.129");
server.sin_port = htons(2000);  //server.sin_port = PORT; //Port: 2000

/* bind socket */
//if(bind(sock_1, (struct sockaddr *)&server, sizeof(server)));
int bindreturn = (bind(sock_1, (struct sockaddr *)&server, sizeof(server)));
if(bindreturn == -1)
{
    cout << "bind: " << WSAGetLastError() << endl; //instead of //cout << "bind: " << strerror(errno) << endl; //cout << "bind wsaret: " << wsaret << endl;
    exit(1);
}

listen(sock_1,MAX_QUEUE);
    /* start accepting connection */
    sock_2 = accept(sock_1,0,0);
    if(sock_2 < 0)
    {
        cout << "accept: " << WSAGetLastError() << endl;
        exit(1);
    }

    /* read from sock_2 */
    while(rec_value=recv(sock_2,buf,BUF_SIZE,0))
    {
        if(rec_value < 0)

        {
         cout << "recv: " << WSAGetLastError() << endl;
         exit(1);
        }
        else
        {
            cout << "else" << endl;
            send(sock_2,"1,2,3",strlen("1,2,3"),0);
        }
    }

    cout << "Ending connection" << endl;
    closesocket(sock_1);
    closesocket(sock_2);
    cout << "End TCP/IP Server" << endl;

    WSACleanup();
return 0;
}

The console shows the following after/during running the program in one or less seconds:

Hello World!
wsaret: 0
Start TCP/IP Server
bind: 0

What can I do, that the server waits for an connection partner?

Thanks in advance.

Regards matl

Edit: Added a few lines of code at the beginning, which I forgot before. Edit: Code update Edit: Code update

Upvotes: 0

Views: 3574

Answers (2)

user207421
user207421

Reputation: 310980

I'm going to comment in detail on the original code you posted.

cout << "Start TCP/IP Server" << endl;

//int sock_1,sock_2;     /* file descriptors for sockets */
int sock_1, sock_2;
int rec_value, length;
char buf[BUF_SIZE];

//struct sockaddr_in server;
sockaddr_in server;

/* create stream socket in internet domain*/
sock_1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//0);

Missing test here. You must test the result for -1 along these lines:

if (sock_1 == -1)
{
    cout << "socket creation error: " << WSAGetLastError() << endl;
    exit(1); // or some other measure to prevent continuation
}

Back to your code:

/* build address in internet domain */
server.sin_family = AF_INET;

/* everyone is allowed to connet to server */
server.sin_addr.s_addr = INADDR_ANY; //inet_addr("192.168.145.129");
server.sin_port = PORT; //Port: 2000

That should be

server.sin_port = htons(PORT);

Back to your code:

/* bind socket */
int bindreturn = bind(sock_1, (struct sockaddr *)&server, sizeof(server));
cout << "bindreturn: " << bindreturn << endl;

Inadequate. Here again you need to test for -1, and print WSAGetLastError() and exit if you got it.

listen(sock_1,MAX_QUEUE);

Untested. Here again you need to test for -1 etc.

    /* start accepting connection */
    //system("pause");
    sock_2 =accept(sock_1,0,0);
    //system("pause");
    cout << "acceptreturn: " << sock_2 << endl;

Inadequate again, see above.

    /* read from sock_2 */
    while(rec_value=recv(sock_2,buf,BUF_SIZE,0))
    {
        if(rec_value<0)
        {
         cout << "error: " << rec_value << endl;
         exit(1);
        }

Test is incorrect. A system call indicates error by returning exactly -1, not just any value < 0. A socket FD for example returned by socket() or accept() can be negative, or any value other than -1.

        else
        {
            cout << "else" << endl;
            send(sock_2,"1,2,3",strlen("1,2,3"),0);
        }
    }
closesocket(sock_1);
closesocket(sock_2);

cout << "End TCP/IP Server" << endl;

return 0;

It is apparent from the closesocket() calls that you're using Winsock, in which case both WSAStart() and WSACleanup() are missing.

Upvotes: 3

Danny_ds
Danny_ds

Reputation: 11406

How is PORT defined?

You should use:

server.sin_port = htons(PORT); //Port: 2000

Is your IP-address correct?

All your calls are receiving SOCKET_ERROR (-1), so you should check lasterror to get more information.

Not sure (on Windows here), but shouldn't those be unsigned int's?

int sock_1, sock_2;

Update:

Ok, you seem to be using Qt on Windows.

For Qt, you might as well use the Qt libraries.

On Windows in general, you could use the free MS Visual Studio.

You also need to call WSAStartup() like this:

WSADATA wsaData;
int wsaret = WSAStartup(MAKEWORD( 4, 4 ), &wsaData);
// check wsaret

// more code here

WSACleanup();

Also use SOCKET:

SOCKET sock_1, sock_2;

Check the errorcodes with WSAGetLastError().

Upvotes: 2

Related Questions