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>
#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)
{
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_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;
}
}
}
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);
}
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)
{
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