Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello everybody,

I'm new in C (as in programming) and I'm studying Windows Sockets.
I wanna write simple chat between server and 2 clients (perfectly server must send messages for everybody, client only for server) and I stucked with a problem.

What I have tried:

From **server** part I can't receive messages from client before I send message TO client. Then I loose opportunity to send messages because of cursos.

From **client** part: client doesn't receive server message. What's the reason? I checked if read and write file descriptors are avaliable (status = 1).

Also If I'm trying to send messages from client and then send message from server, I can type in clien console only once and then get 10053 error (An established connection was aborted by the software in your host computer, possibly due to a data transmission time-out or protocol error) but can't find a bug in server part. After that in server part where I check write and read FD I'm starting receiving my debug messages, these descriptors got status = 0 and I don't see why (probablybecause there is no activity in socket? As it's multiplexing i/o, but I'm more interested in my message problem).

This is **server** output:
Setup SERVER socket descriptor number: 272
We have 1 user online
New client 127.0.0.1:64590
Read FD: 1
Write FD: 1
Server -> Client: Check after 1 and 2
Read FD: 1
Write FD: 1
Client -> Server: Check 1
Check 2

Read FD: 0
Write FD: 0


This is **client** output:
Attempt to connect 127.0.0.1:3765
Local address: 127.0.0.1:3765 of server:
Connection with 127.0.0.1
Client -> Server: Check 1
Client -> Server: Check 2
Client -> Server: trying to write smth
Client -> Server: aaand fail
Send error - Error code: 10053


This is the code of Server:

#pragma comment(lib, "ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
//#include "list.h"

#define PRINTUSERS if (nclients)\
    printf("We have %d user online\n", nclients);\
    else printf("No users online\n***************\n");

#define PORT 3765
#define BACKLOG 10
#define MAXDATASIZE 1024
#define MAXUSERSONLINE 64

int main(int argc, char* argv[])
{
    struct sockaddr_in serverAddr;
    struct sockaddr_in clientAddr;

    SOCKET socketDescriptor;
    fd_set readSocketDescriptor;
    fd_set writeSocketDescriptor;
    int newSocketDescriptor;

    WSADATA wsaData;
    WORD wsaStart;
    timeval tv;

    int retVal;
    int clientAddrSize = sizeof(clientAddr);
    char bufferData[MAXDATASIZE] = { 0 };
    int nclients = 0;
    int numBytes = 0;

    if (argc > 1)
    {
        printf("Uses: <chatserver>\n");
        return -1;
    }
    do
    {
        if ((wsaStart = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
        {
            printf("WSAStartup error ");
            break;
        }
        if ((socketDescriptor = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
        {
            printf("Socket error ");
            closesocket(socketDescriptor);
            break;
        }

        serverAddr.sin_family = AF_INET;
        serverAddr.sin_port = htons(PORT);
        serverAddr.sin_addr.s_addr = INADDR_ANY;

        if (bind(socketDescriptor, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
        {
            printf("Bind error ");
            closesocket(socketDescriptor);

            break;
        }
        if (listen(socketDescriptor, BACKLOG) == SOCKET_ERROR)
        {
            printf("Listening error ");
            closesocket(socketDescriptor);
            break;
        }

        printf("Setup SERVER socket descriptor number: %d\n", socketDescriptor);
        tv.tv_sec = 5;

        while (1)
        {
            // Do not forget to put after WHILE(1)
            FD_ZERO(&readSocketDescriptor);
            FD_ZERO(&writeSocketDescriptor);
            FD_SET(socketDescriptor, &readSocketDescriptor);
            FD_SET(socketDescriptor, &writeSocketDescriptor);

            if ((retVal = select(socketDescriptor + 1, &readSocketDescriptor, &writeSocketDescriptor, NULL, &tv)) == SOCKET_ERROR)
            {
                printf("Select error ");
                break;
            }

            if ((FD_ISSET(socketDescriptor, &readSocketDescriptor)) != 0)
            {
                if ((newSocketDescriptor = accept(socketDescriptor, (struct sockaddr *)&clientAddr, &clientAddrSize)) == SOCKET_ERROR)
                {
                    printf("Accept error ");
                    break;
                }

                createSocketInformation(newSocketDescriptor);
                getSocketInformation(newSocketDescriptor);

                nclients++; PRINTUSERS
                printf("New client %s:%d \n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
                //FD_CLR(socketDescriptor, &readSocketDescriptor);
                FD_SET(newSocketDescriptor, &readSocketDescriptor);
                FD_SET(newSocketDescriptor, &writeSocketDescriptor);

                printf("Read FD: %d\n", FD_ISSET(newSocketDescriptor, &readSocketDescriptor));
                printf("Write FD: %d\n", FD_ISSET(newSocketDescriptor, &writeSocketDescriptor));
                printf("Server -> Client: ");
                fgets(&bufferData[0], sizeof(bufferData), stdin);

                if (FD_ISSET(newSocketDescriptor, &writeSocketDescriptor) != 0)
                {

                    if (send(newSocketDescriptor, &bufferData[0], MAXDATASIZE, 0) == SOCKET_ERROR)
                    {
                        printf("Send error ");
                        freeSocketInformation(newSocketDescriptor);
                        break;
                    }
                //FD_CLR(newSocketDescriptor, &writeSocketDescriptor);
                //FD_SET(newSocketDescriptor, &writeSocketDescriptor);
                }
            }
            printf("Read FD: %d\n", FD_ISSET(newSocketDescriptor, &readSocketDescriptor));
            printf("Write FD: %d\n", FD_ISSET(newSocketDescriptor, &writeSocketDescriptor));
            if (FD_ISSET(newSocketDescriptor, &readSocketDescriptor) != 0)
            {
                if ((numBytes = recv(newSocketDescriptor, &bufferData[0], MAXDATASIZE, 0)) == SOCKET_ERROR)
                {
                    printf("Recv failed \n");
                    freeSocketInformation(newSocketDescriptor);
                    break;
                }

                bufferData[numBytes] = '\0';
                printf("Client -> Server: %s\n", &bufferData[0]);
                if (numBytes == -1)
                {
                    printf("One user has disconnected");
                    nclients--;
                    PRINTUSERS
                }
                else
                {
                    char *testmsg = "Hello, new user, you're welcome\n";
                    if (send(newSocketDescriptor, testmsg, strlen(testmsg), 0) == SOCKET_ERROR)
                    {
                        printf("Send error ");
                        freeSocketInformation(newSocketDescriptor);
                        break;
                    }
                    FD_CLR(newSocketDescriptor, &readSocketDescriptor);
                }
                FD_SET(newSocketDescriptor, &readSocketDescriptor);
            }
            /*else
            {
                printf("Sorry, time limit is expired, there is no active sockets\n");
                freeSocketInformation(newSocketDescriptor);
            }*/
            closesocket(newSocketDescriptor);
        }
        closesocket(socketDescriptor);
    } while (FALSE);
    printf("- Error code: %d\n", WSAGetLastError());
    WSACleanup();
    return 0;
}

And the client part:
#pragma comment(lib, "ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>

#define SERVERADDR argv[1]
#define PORT 3765
#define MAXDATASIZE 1024

int main(int argc, char *argv[])
{
    struct sockaddr_in serverAddr = { 0 };
    struct sockaddr_in clientAddr = { 0 };
    SOCKET socketDescriptor;
    WSADATA wsaData;
    fd_set readSet;
    fd_set writeSet;
    timeval tv;

    char bufferData[MAXDATASIZE];
    int numBytes;
    unsigned long int nb = 1;
    int retVal;

    if (argc != 2)
    {
        printf("Uses: <client> <hostname>\nExample: \"client 127.0.0.1\"\n");
        return -1;
    }
    do
    {
        if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        {
            printf("WSAStartup error ");
            break;
        }
        if (gethostbyname(SERVERADDR) == NULL)
        {
            printf("Gethostbyname error ");
            break;
        }
        if ((socketDescriptor = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
        {
            printf("Socket error ");
            break;
        }
        if (ioctlsocket(socketDescriptor, FIONBIO, (unsigned long *)&nb) != 0)
        {
            printf("ioctlsocket error ");
            break;
        }

        serverAddr.sin_family = AF_INET;
        serverAddr.sin_port = htons(PORT);
        serverAddr.sin_addr.s_addr = inet_addr(SERVERADDR);

        printf("Attempt to connect %s:%d\n", inet_ntoa(serverAddr.sin_addr), htons(serverAddr.sin_port));
        tv.tv_sec = 20;

        if (connect(socketDescriptor, (sockaddr *)&serverAddr, sizeof(serverAddr)))
        {
            getsockname(socketDescriptor, (struct sockaddr *)&clientAddr, (int*)sizeof(clientAddr));
            printf("Local address: %s:%d of server:\n", inet_ntoa(serverAddr.sin_addr), ntohs(serverAddr.sin_port));
            FD_ZERO(&writeSet);
            FD_SET(socketDescriptor, &writeSet);
            if ((retVal = select(socketDescriptor + 1, NULL, &writeSet, NULL, &tv)) == SOCKET_ERROR)
            {
                printf("Send non-blocking error ");
                break;
            }
            else if (retVal == 0)
            {
                printf("Non-blocking connect time limit is expired");
                break;
            }
        }
        printf("Connection with %s\n", SERVERADDR);

        while (1)
        {
            FD_ZERO(&readSet);
            FD_ZERO(&writeSet);
            FD_SET(socketDescriptor, &readSet);
            FD_SET(socketDescriptor, &writeSet);

            if ((retVal = select(socketDescriptor + 1, &readSet, &writeSet, NULL, &tv)) == SOCKET_ERROR)
            {
                printf("Select error ");
                break;
            }
            else if (retVal == 0)
            {
                printf("Time limit is expired ");
                continue;
            }
            char *testmsg = "Hello, I'm a new user online\n";
            printf("Client -> Server: ");
            fgets(&bufferData[0], sizeof(bufferData), stdin);
            if (FD_ISSET(socketDescriptor, &writeSet) != 0)
            {
                //send(socketDescriptor, testmsg, strlen(testmsg), 0);
                if (send(socketDescriptor, &bufferData[0], strlen(&bufferData[0]), 0) == SOCKET_ERROR)
                {
                    printf("Send error ");
                    break;
                }
            }

            if (FD_ISSET(socketDescriptor, &readSet) != 0)
            {
                if ((numBytes = recv(socketDescriptor, &bufferData[0], MAXDATASIZE, 0)) == SOCKET_ERROR)
                {
                    printf("Recv error ");
                    break;
                }
                bufferData[numBytes] = '\0';
                printf("Server -> Client: %s\n", &bufferData[0]);
            }
        }
    } while (FALSE);
    printf("- Error code: %d\n", WSAGetLastError());
    closesocket(socketDescriptor);
    WSACleanup();
    return 0;
}

Thanks for any help
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900