Click here to Skip to main content
15,887,477 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm trying to write client / server application with Multiplexing inp/out. Here is my code and after I'll explain what my problem is.

Client:

#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 destAddr = {0};
    SOCKET socketDescriptor;
    WSADATA wsaData;
    fd_set readSet;
    fd_set writeSet;
    timeval tv;
    fd_set readSocketDescriptor;
    fd_set writeSocketDescriptor;

    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;
        }

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

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

        if (connect(socketDescriptor, (sockaddr *)&destAddr, sizeof(destAddr)))
        {
            printf("Connect error ");
            FD_ZERO(&writeSet);
            FD_SET(socketDescriptor, &writeSet);
            retVal = select(socketDescriptor + 1, NULL, &writeSet, NULL, &tv);
            if (retVal == 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);

            retVal = select(1, &readSet, &writeSet, NULL, &tv);

            if (retVal == SOCKET_ERROR)
            {
                printf("Select error ");
                break;
            }
            else if (retVal == 0)
            {
                printf("Time limit is expired ");
                continue;
            }

            char *testmsg = "Hello, world!\n";
            if (FD_ISSET(socketDescriptor, &writeSet) != 0)
            {
                if (send(socketDescriptor, testmsg, strlen(testmsg), 0) == SOCKET_ERROR)
                {
                    printf("Send error ");
                    break;
                }
                printf("Send function - OK\n");
            }
            if (FD_ISSET(socketDescriptor, &readSet) != 0)
            {
                if ((numBytes = recv(socketDescriptor, bufferData, MAXDATASIZE, 0)) == SOCKET_ERROR)
                {
                    printf("Recv error ");
                    break;
                }
                printf("Recv function - OK\n");
            }
            bufferData[numBytes] = '\0';
            printf("Received text: %s\n", bufferData);
        }
    } while (FALSE);

    printf("- Error code: %d\n", WSAGetLastError());
    closesocket(socketDescriptor);
    WSACleanup();
    return 0;
}


Server:

C++
<pre>Sorry for a long pause, I was away during long weekends.
First of all, thank you for all your reponses.
When I tried to close SocketDescriptor my client stopped working completely. I rewrote a little bit my server, could you check it, please? I still have problems with repeated message and I have error code in client-output (10054, can't fix it).

And I also wrote a structure client and pushBack function to add my new connected clients to the list but not sure if it works fine. It seems I add smth wrong there in while(1) cycle.

<pre>#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

struct client
{
	int numClient;
	struct client* next;
};

void print(struct client* head);
int pushBack(struct client** head, int numClient);
int checkSockOpt(int socket);

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;

	// LIST TEST #1
	struct client* head = 0;
	pushBack(&head, 111);
	pushBack(&head, 222);
	pushBack(&head, 999);
	print(head); //

	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;
		}

		while (1)
		{

			FD_ZERO(&readSocketDescriptor);
			FD_ZERO(&writeSocketDescriptor);
			FD_SET(socketDescriptor, &readSocketDescriptor);
			FD_SET(socketDescriptor, &writeSocketDescriptor);

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

			// Do not forget to put after WHILE(1)
			if ((retVal = select(socketDescriptor + 1, &readSocketDescriptor, &writeSocketDescriptor, NULL, &tv)) == SOCKET_ERROR)
			{
				printf("Select error ");
				break;
			}
			if ((FD_ISSET(socketDescriptor, &readSocketDescriptor)) != 0)
			{
				printf("CHECK FD_ISSET value #1: %d\n", FD_ISSET(socketDescriptor, &readSocketDescriptor));
				//int clientList[MAXUSERSONLINE] = { 0 };
				//for (int i = 0; i <= MAXUSERSONLINE; i++)
				//{

				if ((newSocketDescriptor = accept(socketDescriptor, (struct sockaddr *)&clientAddr, &clientAddrSize)) == SOCKET_ERROR)
				{
					printf("Accept error ");
					break;
				}
				//	newSocketDescriptor = clientList[i];
				struct client* head = 0;
				pushBack(&head, newSocketDescriptor);
				print(head); //
				nclients++; PRINTUSERS

					printf("Server got connection from %s\n", inet_ntoa(clientAddr.sin_addr));
				FD_SET(newSocketDescriptor, &readSocketDescriptor);
				//FD_CLR(socketDescriptor, &readSocketDescriptor);

				printf("CHECK FD_ISSET value #2: %d\n", (FD_ISSET(socketDescriptor, &readSocketDescriptor)));
				printf("newSocketDescriptor = %d, READ_FD status #1 after accept = %d\n", newSocketDescriptor, FD_ISSET(socketDescriptor, &readSocketDescriptor));
				checkSockOpt(newSocketDescriptor);

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

					pushBack(&head, newSocketDescriptor);
					print(head);
					//RECV function
					if ((numBytes = recv(newSocketDescriptor, bufferData, MAXDATASIZE, 0)) == SOCKET_ERROR)
					{
						printf("Recv error ");
						break;
					}

					bufferData[numBytes] = '\0';
					printf("Recv: retVal = %d, bufferData = %s\n", retVal, bufferData);
					printf("newSocketDescriptor = %d, READ_FD status #2 after recv = %d\n", newSocketDescriptor, FD_ISSET(socketDescriptor, &readSocketDescriptor));
					if (numBytes == -1)
					{
						printf("One user has disconnected");
						nclients--;
						PRINTUSERS
					}
					else
					{
						// SEND message to CLIENT
						char *testmsg = "Hello, world!\n";
						if (send(newSocketDescriptor, testmsg, strlen(testmsg), 0) == SOCKET_ERROR)
						{
							printf("Send error ");
							break;
						}
						FD_CLR(newSocketDescriptor, &readSocketDescriptor);
					}
					printf("newSocketDescriptor = %d, READ_FD status #3 after send = %d\n", newSocketDescriptor, FD_ISSET(socketDescriptor, &readSocketDescriptor));
					FD_SET(newSocketDescriptor, &readSocketDescriptor);
					closesocket(newSocketDescriptor);
				}
				//closesocket(newSocketDescriptor);
				//}
			}
			else
			{
				printf("Sorry, time limit is expired, there is no active sockets\n");
			}
		}

	} while (FALSE);
	printf("- Error code: %d\n", WSAGetLastError());
	closesocket(socketDescriptor);
	WSACleanup();
	return 0;
}

// Check Socket Option
int checkSockOpt(int socket)
{
	int optVal = 0;
	int optLen = sizeof(int);
	if (getsockopt(socket, SOL_SOCKET, SO_ACCEPTCONN, (char*)&optVal, &optLen) != SOCKET_ERROR)
	{
		printf("SockOpt Value: %ld. Error code: %d\n", optVal, WSAGetLastError());
	}
	return 0;
}

// Print Client List
void print(struct client* head)
{
	struct client* list = head;
	while (list != 0)
	{
		printf("Client socket %d successfully added to the list\n", list->numClient);
		list = list->next;
	}
}

void printAllFD(struct client* head)
{
	struct client* list = head;
	while (list != 0)
	{
		printf("Client socket %d successfully added to the list\n", list->numClient);
		list = list->next;
	}
}

// pushBack for Client 
int pushBack(struct client** head, int numClient)
{
	//struct client* fd = 0;
	struct client* fd = (struct client*)malloc(sizeof(struct client));
	struct client* list = *head;
	fd->numClient = numClient;
	fd->next = 0;

	if (list == 0)
	{
		*head = fd;
		return 0;
	}
	while (list->next != 0)
	{
		list = list->next;
	}
	list->next = fd;
	return 0;
}

That's server output:
SockOpt Value: 1. Error code: 0
Setup Socket descriptor number: 256
Socket value after "Select": 256
CHECK FD_ISSET value #1: 1
We have 1 user online
Server got connection from 127.0.0.1
CHECK FD_ISSET value #2: 1
Checking now newSocketDescriptor = 256, readfs(j) status = 1
SockOpt Value: 1. Error code: 0
Recv error - Error code: 10057 

And client output:
Attempt to connect 127.0.0.1:3765
Connect error Connection with 127.0.0.1
Send function - OK
Received text: ä
Send function - OK
Received text: ä
Send function - OK
Received text: ä
Send function - OK
Received text: ä
Send error - Error code: 10054


What I have tried:

As I understand I receive a few "Received text"s as my send and recv function (client part) are in while(1) cycle. What should I do with that? To get them out of cycle to make the message transitted only once or what? Can't imagine the way in my case.

Ihave a thought that server is in attempt of one message but as client is trying to send few (because of while(1)) the connection is interrupted and I get 10054 error.How it can be fixed?

I also tried to check socket option using "getsockopt"and it should return 0 if everyting's alright, I got 1. What's wrong?

And I also can't get how to fix my "Recv error" (code 10057) in client part.

P.S. Before I came to this solution I fixed around 7 errors and some bugs but completely stucked in this part. I'll appreciate any help and advices. Thanks

Error 10054: Connection reset by peer.
An existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, the host or remote network interface is disabled, or the remote host uses a hard close (see setsockopt for more information on the SO_LINGER option on the remote socket). This error may also result if a connection was broken due to keep-alive activity detecting a failure while one or more operations are in progress. Operations that were in progress fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.

Error 10057: Socket is not connected.
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using sendto) no address was supplied. Any other type of operation might also return this error—for example, setsockopt setting SO_KEEPALIVE if the connection has been reset.
Posted
Updated 25-Apr-17 10:27am
v7
Comments
Patrice T 20-Apr-17 16:30pm    
and "10054 error." is supposed to mean something to us ?
GeorgeZv 20-Apr-17 16:32pm    
Error 10054: Connection reset by peer.
An existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, the host or remote network interface is disabled, or the remote host uses a hard close (see setsockopt for more information on the SO_LINGER option on the remote socket). This error may also result if a connection was broken due to keep-alive activity detecting a failure while one or more operations are in progress. Operations that were in progress fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.

Error 10057: Socket is not connected.
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using sendto) no address was supplied. Any other type of operation might also return this error—for example, setsockopt setting SO_KEEPALIVE if the connection has been reset.

Patrice T 20-Apr-17 16:37pm    
Use Improve question to update your question.
So that everyone can pay attention to this information.
GeorgeZv 20-Apr-17 16:38pm    
Ok, thanks. I'll fix it.

1 solution

Your server code breaks here with error 10057 (as indicated by the output):
if ((numBytes = recv(socketDescriptor, bufferData, MAXDATASIZE, 0)) == SOCKET_ERROR)
{
    printf("Recv error ");
    break;
}
The reason is that socketDescriptor is not a connected socket. The connected socket is the one returned by accept(): newSocketDescriptor.

Solution:
Replace socketDescriptor by newSocketDescriptor in all calls that are related to the connection (generally all socket functions after the accept() call). Check also the FD_SET() and and FD_CLR() calls because they seem to be also using mixed up sockets.
 
Share this answer
 
Comments
GeorgeZv 21-Apr-17 4:31am    
Thank you, it worked if I change my socketDescriptor. As I see everything's ok with FD_SET() and FD_CLR().

Now my server send and receive messages but not without issues. Server can return from 2 till 5 "Hello"-messages, from the client the messages are in cycle and I get them till when my my tv.tv_sec = 5 is expired. I can't clearly get how to separate sending messages from while(1) cycle not touching send and recv.
Jochen Arndt 21-Apr-17 4:54am    
Thank you for accepting my solution.

To be honest, I can't understand your new problem (what conditions / timeouts should be handled).
GeorgeZv 21-Apr-17 5:13am    
Sorry, I gave incomplete information.

Well, now my server output looks like that:
Setup socket descriptor number: 120
Socket value after "Select": 120
CHECK FD_ISSET value #1: 1
We have 1 user online
Server got connection from 127.0.0.1
CHECK FD_ISSET value #2: 1
Checking now newSocketDescriptor = 120, readfs(j) status = 1
SockOpt Value: 0. Error code: 0
Checking now newSocketDescriptor = 120, readSocketDescriptor status = 1
Recv: retVal = 1, bufferData = Hello, world!
Hello, world!
Hello, world!
Hello, world!

No users online
***************
CHECK FD_ISSET value #1: 1 


And client in endless cycle:
Send function - OK
Received text: Hello, world!

Send function - OK
Received text: Hello, world!

Send function - OK
Received text: Hello, world!

Send function - OK
Received text: Hello, world!

Send function - OK
Received text: Hello, world!

Send function - OK
Received text: Hello, world!


I need to receive only 1 message from server and only 1 message from client. I suppose it's because while(1) cycle but can't get how to actually get out of it and to get what I want. I receive messages and it's already good but not enough :)
Jochen Arndt 21-Apr-17 5:40am    
If you want to stop after one message exit, close the connections on client and server afterwards.

Client:
Remove the while(1) loop (requires restarting the app to reconnect).
If you want to reconnect without closing the app you have to implement appropriate code.

Server:
Close newSocketDescriptor at the end of the FD_ISSET() block. With the next connection attempt that check will be true again and a new socket is created when accepting.

Note that there is another error in your code:
When terminating the app, newSocketDescriptor is actually closed but it should be SocketDescriptor.
GeorgeZv 25-Apr-17 16:26pm    
Sorry for a long pause, I was away during long weekends.
First of all, thank you for all your reponses.
When I tried to close SocketDescriptor my client stopped working completely. I rewrote a little bit my server, could you check it, please? I still have problems with repeated message and I have error code in client-output (10054, can't fix it).

And I also wrote a structure client and pushBack function to add my new connected clients to the list but not sure if it works fine. It seems I add smth wrong there in while(1) cycle.

#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

struct client
{
	int numClient;
	struct client* next;
};

void print(struct client* head);
int pushBack(struct client** head, int numClient);
int checkSockOpt(int socket);

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;

	// LIST TEST #1
	struct client* head = 0;
	pushBack(&head, 111);
	pushBack(&head, 222);
	pushBack(&head, 999);
	print(head); //

	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;
		}

		while (1)
		{

			FD_ZERO(&readSocketDescriptor);
			FD_ZERO(&writeSocketDescriptor);
			FD_SET(socketDescriptor, &readSocketDescriptor);
			FD_SET(socketDescriptor, &writeSocketDescriptor);

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

			// Do not forget to put after WHILE(1)
			if ((retVal = select(socketDescriptor + 1, &readSocketDescriptor, &writeSocketDescriptor, NULL, &tv)) == SOCKET_ERROR)
			{
				printf("Select error ");
				break;
			}
			if ((FD_ISSET(socketDescriptor, &readSocketDescriptor)) != 0)
			{
				printf("CHECK FD_ISSET value #1: %d\n", FD_ISSET(socketDescriptor, &readSocketDescriptor));
				//int clientList[MAXUSERSONLINE] = { 0 };
				//for (int i = 0; i <= MAXUSERSONLINE; i++)
				//{

				if ((newSocketDescriptor = accept(socketDescriptor, (struct sockaddr *)&clientAddr, &clientAddrSize)) == SOCKET_ERROR)
				{
					printf("Accept error ");
					break;
				}
				//	newSocketDescriptor = clientList[i];
				struct client* head = 0;
				pushBack(&head, newSocketDescriptor);
				print(head); //
				nclients++; PRINTUSERS

					printf("Server got connection from %s\n", inet_ntoa(clientAddr.sin_addr));
				FD_SET(newSocketDescriptor, &readSocketDescriptor);
				//FD_CLR(socketDescriptor, &readSocketDes

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