Client-server echo-chat (multiplexing I/O + threads) - c

I just started learning C language and I'm trying to get deal with Windows Sockets.
The problem is the server can accept and send message only once.
I used debug mode and saw that work stops in select() from the server part. It seems fine in client (but I'm not sure) and don't see the problem in my code. But I have such a result. What's wrong?
I noticed that my tv.tv_sec isn't defined and I did that just before select, nothing was changed.
And just to be sure: as I need to receive and send message, I don't need write descriptor in accept(), right?
Client uses CreateThread function where I try to send message. Send is in while(1) cycle in main()
Server part:
int main(int argc, char* argv[])
{
/* definitions, WSAStartup(), socket(), bind(), listen()
Listening socket is a returned value of listen() function*/
FD_ZERO(&readSet);
FD_ZERO(&writeSet);
while (1)
{
// SELECT (LISTENING SOCKET)
FD_ZERO(&readSet);
FD_SET(listeningSocket, &readSet);
tv.tv_sec = 5;
printf("Listening: Read FD: %d; Write FD : %d;\n", FD_ISSET(listeningSocket, &readSet), FD_ISSET(listeningSocket, &writeSet));
if ((retVal = select(listeningSocket + 1, &readSet, NULL, NULL, 0)) == SOCKET_ERROR)
{
printf("Select error ");
break;
}
else if (retVal == 0)
{
printf(". . .\n");
continue;
}
else
{
// READ SD
if ((FD_ISSET(listeningSocket, &readSet)) != SOCKET_ERROR)
{
if ((newSocketDescriptor = accept(listeningSocket, (struct sockaddr *)&clientAddr, &clientAddrSize)) == SOCKET_ERROR)
{
printf("Accept error ");
break;
}
FD_ZERO(&readSet);
FD_SET(newSocketDescriptor, &readSet);
HOSTENT *hst = gethostbyaddr((const char *)&serverAddr.sin_addr.s_addr, 4, AF_INET);
printf("Welcome %s (%s:%d) new connected\n", hst->h_name, inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
printf("Read FD: %d; Write FD : %d;\n", FD_ISSET(newSocketDescriptor, &readSet), FD_ISSET(newSocketDescriptor, &writeSet));
// READ
if (FD_ISSET(newSocketDescriptor, &readSet) != 0)
{
if ((numBytes = recv(newSocketDescriptor, &bufferData[0], sizeof(bufferData), 0)) == SOCKET_ERROR)
{
printf("Recv failed \n");
freeSocketInformation(newSocketDescriptor);
break;
}
bufferData[numBytes] = '\0';
printf("Client -> Server: %s\n", &bufferData[0]);
}
// WRITE
FD_ZERO(&writeSet);
FD_SET(newSocketDescriptor, &writeSet);
printf("Read FD: %d; Write FD : %d;\n", FD_ISSET(newSocketDescriptor, &readSet), FD_ISSET(newSocketDescriptor, &writeSet));
if (FD_ISSET(newSocketDescriptor, &writeSet) != 0)
{
//fgets(&bufferData[0], sizeof(bufferData), stdin);
if (send(newSocketDescriptor, &bufferData[0], strlen(&bufferData[0]), 0) == SOCKET_ERROR)
{
printf("Send error ");
freeSocketInformation(newSocketDescriptor);
break;
}
bufferData[numBytes] = '\0';
printf("Server -> Client: %s\n", &bufferData[0]);
}
printf("Read FD: %d; Write FD : %d;\n", FD_ISSET(newSocketDescriptor, &readSet), FD_ISSET(newSocketDescriptor, &writeSet));
FD_SET(newSocketDescriptor, &readSet);
}
}
}
//FD_CLR(listeningSocket, &readSet);
closesocket(newSocketDescriptor);
} while (FALSE);
printf("- Error code: %d\n", WSAGetLastError());
closesocket(listeningSocket);
WSACleanup();
return 0;
}
Client part (it uses CreateThread function which is in the end of the code):
/* definitions, socket(), connect()*/
if (ioctlsocket(socketDescriptor, FIONBIO, (unsigned long *)&nb) != 0)
{
printf("ioctlsocket error ");
break;
}
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);
DWORD thID;
printf("Socket Desciptor: %d\n", socketDescriptor);
HANDLE hThread = CreateThread(NULL, NULL, HandleReadThread, (LPVOID)socketDescriptor, NULL, &thID);
printf("Thread ID: %d\n", thID);
while (1)
{
// WRITE
printf("Client -> Server: ");
fgets(&bufferData[0], sizeof(bufferData), stdin);
FD_ZERO(&writeSet);
FD_SET(socketDescriptor, &writeSet);
tv.tv_sec = 5;
if ((retVal = select(socketDescriptor + 1, NULL, &writeSet, NULL, &tv)) == SOCKET_ERROR)
{
printf("Send non-blocking error ");
break;
}
if (FD_ISSET(socketDescriptor, &writeSet) != 0)
{
if (send(socketDescriptor, bufferData, strlen(&bufferData[0]), 0) == SOCKET_ERROR)
{
printf("Send error ");
break;
}
}
}
} while (FALSE);
printf("- Error code: %d\n", WSAGetLastError());
closesocket(socketDescriptor);
WSACleanup();
return 0;
}
DWORD WINAPI HandleReadThread(LPVOID serverSocket)
{
SOCKET socketDescriptor;
socketDescriptor = (SOCKET)serverSocket;
char bufferData[MAXDATASIZE] = { 0 };
int retVal;
fd_set readSet;
timeval tv = { 0 };
tv.tv_sec = 5;
int numBytes;
int nclients = 0;
while (1)
{
FD_ZERO(&readSet);
FD_SET(socketDescriptor, &readSet);
if ((retVal = select(socketDescriptor + 1, &readSet, NULL, NULL, &tv)) == SOCKET_ERROR)
{
printf("Select error. Error code: %d", WSAGetLastError());
break;
}
else if (retVal == 0)
{
//printf(". . .\n");
continue;
}
else
{
//FD_ZERO(socketDescriptor, &readSet);
//FD_SET(socketDescriptor, &readSet);
// READ
if (FD_ISSET(socketDescriptor, &readSet) != 0)
{
if ((numBytes = recv(socketDescriptor, &bufferData[0], sizeof(bufferData), 0)) == SOCKET_ERROR)
{
printf("Recv error in Thread. Error code: %d\n", WSAGetLastError());
break;
}
printf("\nSocket Desciptor: %d\n", socketDescriptor);
bufferData[numBytes] = '\0';
printf("Server -> Client: %s\n", &bufferData[0]);
}
}
}
closesocket(socketDescriptor);
return 0;
}

Well, I solved it by myself. The condition
if ((FD_ISSET(listeningSocket, &readSet)) != 0)
worked for all while(1) cycle, it should has been finished after accept() function.
Also I added these lines in the beginning of while(1) after FD_SET for readSet:
if (newSocketDescriptor)
{
FD_SET(newSocketDescriptor, &readSet);
}
The chat started working but there are a lot of stuffs to work at :)

Related

socket send fails with 10054 error when trying to connect to different port on a separate thread

I'm a newbie in tcp protocol and websocket.
I've estalished a connection between server and client and created another thread to send the packets received from the server to a websocket. And my code looks as below.
This is the server side of a code
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
int iResult;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char portStr[20];
SOCKET ConnectSocket = INVALID_SOCKET;
MSG_PACKET packet;
PQN_DATA_PACKET *ppacket;
PACKET_HEADER *ppacket_header;
queue<PQN_DATA_PACKET *> *pconnectionQ = new queue<PQN_DATA_PACKET *>();
char ps8bufsend[DEFAULT_BUFLEN];
char ps8bufrecv[DEFAULT_BUFLEN];
int packet_idx = 0;
PQN_DATA_PACKET* pstpacket;
int s8ack = 0;
std::string filename, path;
int s32packetlen = 0;
struct sockaddr_in serv_addr = {0};
struct sockaddr_in clnt_addr = {0};
const char* ip = LOCAL_IP;
SOCKET serv_sock = INVALID_SOCKET;
socklen_t clnt_addr_size;
int clnt_sock;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if(serv_sock == -1)
{
printf( "socket() Error..Error --> Code %d ", WSAGetLastError() );
error_handling("socket error");
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = PF_INET;
serv_addr.sin_addr.s_addr = inet_addr(ip);
serv_addr.sin_port = htons(CLIENT_PORT_NUMBER);
if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
{
printf( "bind() Error..Error --> Code %d ", WSAGetLastError() );
error_handling("bind error");
}
if(listen(serv_sock, 5) == -1)
{
printf( "listen() Error..Error --> Code %d ", WSAGetLastError() );
error_handling("listen error");
}
clnt_addr_size = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
if(clnt_sock == -1)
{
printf( "accept() Error..Error --> Code %d ", WSAGetLastError() );
error_handling("accept error");
}
FILE *fp = fopen( argv[1], "r+");
FILE *fpout = fopen("test.txt", "r");
ProcessFile(fp);
for(int i = 0; i < 5; i++)
{
if (i == ORDER_TIME_SETTING)
{
MSG_PDDAU_INFO_PACKET* ps8ptr = new MSG_PDDAU_INFO_PACKET;
s32packetlen = sizeof(MSG_PDDAU_INFO_PACKET);
if (clnt_sock == INVALID_SOCKET)
{
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
iResult = recv(clnt_sock, (char*)ps8ptr, s32packetlen, 0);
if (iResult == -1)
{
//fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
printf("recv failed with error: %ld\n", WSAGetLastError());
return -1;
}
if (ps8ptr->header.msg_id != MSG_PDDAU_INFO_ID && ps8ptr->header.msg_type != MSG_REQUEST_TYPE)
{
printf("Time setting failed\n");
return -1;
}
if(!ps8ptr->time_enable)
{
printf("Time is disabled!\n");
return -1;
}
ps8ptr->header.msg_type = MSG_REQUEST_ACK_TYPE;
iResult = send(clnt_sock, (char*)ps8ptr, sizeof(MSG_PDDAU_INFO_PACKET), 0);
if (iResult == -1)
{
//fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
printf("send failed with error: %ld\n", WSAGetLastError());
return -1;
}
}
else if (i == ORDER_PDDAU_INFO)
{
MSG_PDDAU_INFO_PACKET* ps8ptr = new MSG_PDDAU_INFO_PACKET;
iResult = recv(clnt_sock, (char*)ps8ptr, sizeof(MSG_PDDAU_INFO_PACKET), 0);
if (iResult == -1)
{
//fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
printf("recv failed with error: %ld\n", WSAGetLastError());
return -1;
}
if (ps8ptr->header.msg_id != MSG_PDDAU_INFO_ID && ps8ptr->header.msg_type != MSG_READ_INFO_TYPE)
{
printf("PDDAU Info Setting failed\n");
return -1;
}
ps8ptr->header.msg_type = MSG_READ_INFO_RESPONSE_TYPE;
iResult = send(clnt_sock, (char*)ps8ptr, sizeof(MSG_PDDAU_INFO_PACKET), 0);
if (iResult == -1)
{
//fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
printf("send failed with error: %ld\n", WSAGetLastError());
return -1;
}
}
else if (i == ORDER_RF_INFO)
{
MSG_RF_INFO_PACKET* ps8ptr = new MSG_RF_INFO_PACKET;
iResult = recv(clnt_sock, (char*)ps8ptr, sizeof(MSG_RF_INFO_PACKET), 0);
if (iResult == -1)
{
//fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
printf("recv failed with error: %ld\n", WSAGetLastError());
return -1;
}
if (ps8ptr->header.msg_id != MSG_RF_INFO_ID && ps8ptr->header.msg_type != MSG_READ_INFO_TYPE)
{
printf("PDDAU Info Setting failed\n");
return -1;
}
ps8ptr->header.msg_type = MSG_READ_INFO_RESPONSE_TYPE;
iResult = send(clnt_sock, (char*)ps8ptr, sizeof(MSG_RF_INFO_PACKET), 0);
if (iResult == -1)
{
//fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
printf("send failed with error: %ld\n", WSAGetLastError());
return -1;
}
}
else if(i == ORDER_PD_DATA)
{
printf("Yo 1\n");
MSG_PD_PACKET* ps8ptr = new MSG_PD_PACKET;
iResult = recv(clnt_sock, (char*)ps8ptr, sizeof(MSG_PD_PACKET), 0);
if (iResult == -1)
{
//fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
printf("recv failed with error: %ld\n", WSAGetLastError());
return -1;
}
if (ps8ptr->header.msg_id != MSG_PD_START_ID && ps8ptr->header.msg_type != MSG_REQUEST_TYPE)
{
printf("PDDAU Info Setting failed\n");
return -1;
}
ps8ptr->header.msg_type = MSG_REQUEST_ACK_TYPE;
iResult = send(clnt_sock, (char*)ps8ptr, sizeof(MSG_PD_PACKET), 0);
if (iResult == -1)
{
//fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
printf("send failed with error: %ld\n", WSAGetLastError());
return -1;
}
}
else
{
MSG_PD_PACKET* ps8ptr = new MSG_PD_PACKET;
printf("Yo 2\n");
iResult = recv(clnt_sock, (char*)ps8ptr, sizeof(MSG_PD_PACKET), 0);
if (iResult == -1)
{
fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
if(ps8ptr->header.msg_type != MSG_REQUEST_TYPE || ps8ptr->header.msg_id != MSG_PD_START_ID)
{
printf("PD Sending failed\n");
return -1;
}
ps8ptr->header.msg_type = MSG_REQUEST_ACK_TYPE;
iResult = send(clnt_sock, (char*) ps8ptr, sizeof(MSG_PD_PACKET), 0);
if (iResult == -1)
{
printf("Yo 2\n");
fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
while(fgets(ps8bufsend, ONE_CYCLE, fpout) != NULL)
{
memset(ps8ptr->data,0,ONE_CYCLE);
memcpy(ps8ptr->data, ps8bufsend, ONE_CYCLE);
boost::asio::io_context io;
boost::asio::steady_timer t(io, boost::asio::chrono::milliseconds(83));
packet_idx++;
ps8ptr->header.msg_id = MSG_PD_SEND_ID;
ps8ptr->header.msg_type = MSG_SEND_TYPE;
printf("Yo 3\n");
s8ack = send(clnt_sock,(char*)ps8ptr, sizeof(MSG_PD_PACKET),0);
printf("Yo 4\n");
if (s8ack == -1)
{
printf("Yo 5\n");
//fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
printf("send failed with error: %ld\n", WSAGetLastError());
return -1;
}
This is my client side of the code.
int __cdecl main(int argc, char **argv)
{
PQN_DATA_PACKET* pstpacket;
//int serv_sock;
SOCKET serv_sock = INVALID_SOCKET;
int clnt_sock;
WSADATA wsaData;
int nErrorStatus;
WORD wVersionRequested = MAKEWORD(2, 2);
const char* ip = LOCAL_IP;
struct sockaddr_in serv_addr = {0};
struct sockaddr_in clnt_addr = {0};
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
socklen_t clnt_addr_size;
char buff[255];
int iResult;
queue<PQN_DATA_PACKET *> *pconnectionQ = new queue<PQN_DATA_PACKET *>();
DWORD RunWebServerThreadID;
nErrorStatus = WSAStartup(wVersionRequested, &wsaData);
PACKET_HEADER *ppacket_header;
ppacket_header = new PACKET_HEADER;
std::fstream datfile;
std::string filename, path;
SOCKET ConnectSocket = INVALID_SOCKET;
char ps8bufsend[DEFAULT_BUFLEN];
char ps8bufrecv[DEFAULT_BUFLEN];
int order[] = {ORDER_TIME_SETTING, ORDER_PDDAU_INFO, ORDER_RF_INFO, ORDER_PD_DATA};
int s32packetlen = 0;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
iResult = getaddrinfo(LOCAL_IP, "8081", &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
{
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET)
{
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
if (ConnectSocket == INVALID_SOCKET)
{
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
HANDLE t2 = CreateThread(0, 0, RunWebServerThread, pconnectionQ, 0, &RunWebServerThreadID);
for (int i = 0; i < 5; i++)
{
//while(1)
//{
if(i == ORDER_TIME_SETTING)
{
MSG_PDDAU_INFO_PACKET* ps8ptr = new MSG_PDDAU_INFO_PACKET;
ps8ptr->header.msg_id = MSG_PDDAU_INFO_ID;
ps8ptr->header.msg_type = MSG_REQUEST_TYPE;
ps8ptr->time_enable = 0x01;
s32packetlen = sizeof(MSG_PDDAU_INFO_PACKET);
printf("ConnectSocket=%i\n", ConnectSocket);
iResult = send(ConnectSocket, (char*)ps8ptr, s32packetlen, 0);
if (iResult == -1)
{
fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
memset(ps8ptr, 0, s32packetlen);
iResult = recv(ConnectSocket, (char*)ps8ptr, s32packetlen, 0);
if (iResult == -1)
{
fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
printf("recv result : %d\n",iResult);
printf("header msg_id : %d\n", ps8ptr->header.msg_id);
if (ps8ptr->header.msg_type != MSG_REQUEST_ACK_TYPE)
{
printf("Time setting failed\n");
return -1;
}
delete ps8ptr;
ps8ptr = NULL;
}
else if(i == ORDER_PDDAU_INFO)
{
MSG_PDDAU_INFO_PACKET* ps8ptr = new MSG_PDDAU_INFO_PACKET;
ps8ptr->header.msg_id = MSG_PDDAU_INFO_ID;
ps8ptr->header.msg_type = MSG_READ_INFO_TYPE;
iResult = send(ConnectSocket, (char*)ps8ptr, sizeof(MSG_PDDAU_INFO_PACKET), 0);
if (iResult == -1)
{
fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
memset(ps8ptr, 0, sizeof(MSG_PDDAU_INFO_PACKET));
iResult = recv(ConnectSocket, (char*)ps8ptr, sizeof(MSG_PDDAU_INFO_PACKET), 0);
if (iResult == -1)
{
fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
if (ps8ptr->header.msg_type != MSG_READ_INFO_RESPONSE_TYPE)
{
printf("PDDAU Info Setting failed\n");
return -1;
}
delete ps8ptr;
ps8ptr = NULL;
}
else if(i == ORDER_RF_INFO)
{
MSG_RF_INFO_PACKET* ps8ptr = new MSG_RF_INFO_PACKET;
ps8ptr->header.msg_id = MSG_RF_INFO_ID;
ps8ptr->header.msg_type = MSG_READ_INFO_TYPE;
iResult = send(ConnectSocket, (char*) ps8ptr, sizeof(MSG_RF_INFO_PACKET), 0);
if (iResult == -1)
{
fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
memset(ps8ptr, 0, sizeof(MSG_RF_INFO_PACKET));
iResult = recv(ConnectSocket, (char*)ps8ptr, sizeof(MSG_RF_INFO_PACKET), 0);
if (iResult == -1)
{
fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
if (ps8ptr->header.msg_type != MSG_READ_INFO_RESPONSE_TYPE)
{
printf("RF Info Setting failed\n");
return -1;
}
delete ps8ptr;
}
else if(i == ORDER_PD_DATA)
{
MSG_PD_PACKET* ps8ptr = new MSG_PD_PACKET;
ps8ptr->header.msg_id = MSG_PD_START_ID;
ps8ptr->header.msg_type = MSG_REQUEST_TYPE;
iResult = send(ConnectSocket, (char*) ps8ptr, sizeof(MSG_PD_PACKET), 0);
if (iResult == -1)
{
fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
memset(ps8ptr, 0, sizeof(MSG_PD_PACKET));
iResult = recv(ConnectSocket, (char*)ps8ptr, sizeof(MSG_PD_PACKET), 0);
if (iResult == -1)
{
fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
if (ps8ptr->header.msg_type != MSG_REQUEST_ACK_TYPE)
{
printf("RF Info Setting failed\n");
return -1;
}
delete ps8ptr;
}
else
{
MSG_PD_PACKET *ps8ptr = new MSG_PD_PACKET;
ps8ptr->header.msg_id = MSG_PD_START_ID;
ps8ptr->header.msg_type = MSG_REQUEST_TYPE;
ps8ptr->header.body_len = sizeof(MSG_PD_PACKET);
ps8ptr->ch_idx = 1;
printf("Error?\n");
iResult = send(ConnectSocket, (char*) ps8ptr, sizeof(MSG_PD_PACKET), 0);
if (iResult == -1)
{
fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
memset(ps8ptr, 0, sizeof(MSG_PD_PACKET));
iResult = recv(ConnectSocket, (char*)ps8ptr, sizeof(MSG_PD_PACKET), 0);
if (iResult == -1)
{
fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
if (ps8ptr->header.msg_type != MSG_REQUEST_ACK_TYPE)
{
printf("RF Info Setting failed\n");
return -1;
}
while(1)
{
MSG_PD_PACKET *ps8data = new MSG_PD_PACKET;
printf("Error 2?\n");
iResult = recv(ConnectSocket, (char*)ps8ptr, sizeof(MSG_PD_PACKET), 0);
if (iResult == -1)
{
fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
if(ps8ptr->header.msg_type != MSG_SEND_TYPE || ps8ptr->header.msg_id != MSG_PD_SEND_ID)
{
printf("PD Sending failed. type : %x, id : %x\n", ps8ptr->header.msg_type, ps8ptr->header.msg_id);
return -1;
}
std::lock_guard<std::mutex> lock_guard(queue_mutex2);
(*pconnectionQ).push(pstpacket);
And here is the thread function I run on the client side.
DWORD WINAPI RunWebServerThread(LPVOID lpParameter)
{
//server srv;
//srv.run(tcp::endpoint(tcp::v6(), SERVER_PORT_NUMBER), 1);
int threads(1);
net::io_context ioc{ threads };
queue<PQN_DATA_PACKET *> *pconnectionQ = (queue<PQN_DATA_PACKET *> *)lpParameter;
auto const address = net::ip::make_address(LOCAL_IP);
// Create and launch a listening port
std::make_shared<listener>(ioc, tcp::endpoint{ address, SERVER_PORT_NUMBER }, pconnectionQ)->run();
// Run the I/O service on the requested number of threads
std::vector<std::thread> v;
v.reserve(threads - 1);
for (auto i = threads - 1; i > 0; --i)
v.emplace_back(
[&ioc]
{
ioc.run();
});
ioc.run();
}
As you can see there is no correlation between the port used in the thread function and main socket.
However, here is the output I've got on the server side once I connect frontend websocket.
Yo 3
Yo 4
Yo 3
Yo 4
Yo 5
send failed with error: 10054
Can anyone point out the possible problem with this code?
Thank you in advance.
Okay. I've solved the problem myself.
The reason the connection was closed is because I've been using the wrong type of data packet. It was supposed to be something else other than PQN_DATA_PACKET.
Thus, the thread function died and affected the regular connection since it couldn't handle the right type of the packet.
It was an amateur mistake in my part..
Thanks everyone for focusing on my problem.

How to handle 3 way send() and recv() in BSD socket using C

After sending "wrong" username - client won't start loop from beginning, actually, there is no server asks:?
Dunno how to handle 3 way client-server message sender for such auth. I must understand this to continue such message receiving in further.
client.c:
int is_authenticated = 0;
size_t sendline_s;
while (!is_authenticated) {
recv(sockfd, recvline, MAXLINE, 0);
printf("%s", "server asks:");
fputs(recvline, stdout);
printf("?> ");
fflush(stdout);
while (fgets(sendline, MAXLINE, stdin) != NULL) {
sendline_s = strlen(sendline);
if (sendline[sendline_s-1] == '\n') {
sendline[sendline_s-1] = '\0';
send(sockfd, sendline, sendline_s+1, 0);
puts("username sended");
break;
}
// handling ^Z (EOF) here
//
}
recv(sockfd, recvline, MAXLINE, 0);
printf("\nawaiting for server ACK\n");
puts(recvline);
if (strcmp(recvline, "ACCEPTED_AUTH") == 0) {
puts("authentication complete successful");
is_authenticated = 1;
}
else {
puts("authentication declined");
}
}
server.c
int is_authenticated = 0;
char *accepted = "ACCEPTED_AUTH";
char *name = "kaldown";
char *wrong = "wrong";
size_t name_s = strlen(name);
size_t accepted_s = strlen(accepted);
size_t wrong_s = strlen(wrong);
while (!is_authenticated) {
send(connfd, name, name_s+1, 0);
puts("authentication request was send");
recv(connfd, buf, MAXLINE, 0);
printf("username was recieved: ");
puts(buf);
if (strcmp(buf, name) == 0) {
puts("hurray");
send(connfd, accepted, accepted_s+1, 0);
is_authenticated = 1;
//break;
}
else {
puts("WRONG NAME");
send(connfd, wrong, wrong_s+1, 0);
}
}
But, If i send right username - it passes the block and everything goes well.
server:
while (!is_authenticated) {
if ((n = recv(connfd, buf, MAXLINE-1,0))== -1) {
perror("recv");
exit(1);
}
else if (n == 0) {
printf("Connection closed\n");
//So I can now wait for another client
break;
}
printf("\n%d truely recieved", n);
buf[n] = '\0';
printf("Server:Msg Received %s\n", buf);
if (strcmp(buf, "DONE") == 0) {
strcpy(buf, "DONE");
if ((send(connfd,buf, strlen(buf),0))== -1)
{
fprintf(stderr, "Failure Sending Message\n");
close(connfd);
break;
}
puts("KONEC");
is_authenticated = 1;
}
else {
if ((send(connfd,buf, strlen(buf),0))== -1)
{
fprintf(stderr, "Failure Sending Message\n");
close(connfd);
break;
}
}
printf("Server:Msg being sent: %s\nNumber of bytes sent: %d\n", buf, strlen(buf));
}
client:
while (!is_authenticated) {
printf("Client: Enter Data for Server:\n");
if (fgets(sendline, MAXLINE-1, stdin) != NULL) {
if (sendline[(strlen(sendline)-1)] == '\n') {
sendline[strlen(sendline)-1] = '\0';
if ((send(sockfd,sendline, strlen(sendline),0))== -1) {
fprintf(stderr, "Failure Sending Message\n");
close(sockfd);
exit(1);
}
else {
printf("Client:Message being sent: %s\n",sendline);
n = recv(sockfd, sendline, sizeof(sendline),0);
if ( n <= 0 )
{
printf("Either Connection Closed or Error\n");
//Break from the While
break;
}
sendline[n] = '\0';
if (strcmp(sendline, "DONE") == 0) {
puts("AUTH PASSED");
is_authenticated = 1;
}
printf("Client:Message Received From Server - %s\n",sendline);
}
}
//EOF
}
}

Server closes connection before replying

I'm following the MSDN lessons about TCP/IP client; my issue is that the server isn't replying and the connection closes after I send the Headers.
const char *USR_PORT = "80";
#define BUFF_LEN 512
char recv_buf[BUFF_LEN];
const char HEADER_TO_SEND[] = "HEAD / HTTP/1.1\r\nHost: www.microsoft.com\r\nUser-Agent: RequestHeaderC\r\n\r\n";
{...}
do {
iRes = recv(ConnSocket, recv_buf, BUFF_LEN, 0);
if (iRes > 0)
{
printf("Bytes received: %d\n", iRes);
for (i = 0; (i < iRes) && recv_buf[i] != '\0'; i++)
printf("%c", recv_buf[i]);
}
else if (iRes == 0)
printf("Connection closed by the server.\n");
else printf("Error: %d\n", WSAGetLastError());
} while (iRes > 0);
I'm almost sure the connection was fine as I sent with success the bytes.
I don't receive any byte at all.
The other codes are almost the same as the ones in the tutorial, that's why I haven't posted them. If needed, I will
The server doesn't close the connection immediately if I remove this line:
shutdown(ConnSocket, SD_SEND);
But then I don't get any answer anyways, even if I add
Connection: close\r\n
in the headers
Full code:
const char *USR_PORT = "80";
#define BUFF_LEN 512
char USR_ADDR[] = "www.microsoft.com";
const char HEADER_TO_SEND[] = "HEAD / HTTP/1.1\r\nHost: www.microsoft.com\r\nUser-Agent: RequestHeaderC\r\nConnection: close\r\n\r\n";
int main()
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("Error: Wsastartup\n");
exit(1);
}
int iRes;
addrinfo *result, *ptr, addr;
SecureZeroMemory(&addr, sizeof(addr));
addr.ai_family = AF_INET;
addr.ai_protocol = IPPROTO_TCP;
addr.ai_socktype = SOCK_STREAM;
iRes = getaddrinfo(USR_ADDR, USR_PORT, &addr, &result);
if ( iRes != 0 )
{
printf("Error: getaddrinfo");
WSACleanup();
exit(2);
}
SOCKET ConnSocket;
ptr = result;
ConnSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnSocket == INVALID_SOCKET)
{
printf("Error: socket: %ld \n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
exit(3);
}
if (connect(ConnSocket, ptr->ai_addr, (int)ptr->ai_addrlen) )
{
closesocket(ConnSocket);
ConnSocket = INVALID_SOCKET;
}
if (ConnSocket == INVALID_SOCKET)
{
printf("Invalid Socket\n");
exit(4);
}
const char *send_buf = HEADER_TO_SEND;
char recv_buf[BUFF_LEN];
if ((iRes = send(ConnSocket, send_buf, strlen(send_buf) - 1, 0)) == SOCKET_ERROR)
{
printf("Error: send\n");
closesocket(ConnSocket);
WSACleanup();
exit(5);
}
int i;
for (i = 0; i < iRes; i++)
printf("%c", send_buf[i]);
printf("Bytes sent: %d\n", iRes);
//if (shutdown(ConnSocket, SD_SEND) == SOCKET_ERROR)
//{
// printf("Error: shutdown: %d\n", WSAGetLastError());
// closesocket(ConnSocket);
// WSACleanup();
// exit(6);
//}
//do {
iRes = recv(ConnSocket, recv_buf, sizeof(recv_buf)-1, 0);
if (iRes > 0)
{
printf("Bytes received: %d\n", iRes);
recv_buf[iRes] = '\0';
for (i = 0; i < iRes; i++)
printf("%c", recv_buf[i]);
}
else if (iRes == 0)
printf("Connection closed by the server.\n");
else printf("Error: %d\n", WSAGetLastError());
//} while (iRes > 0);
getchar();
getchar();
closesocket(ConnSocket);
WSACleanup();
return 0;
}

what are the changes from the linux code to qnx code?

int CreateSocket()
{
//pthread_attr_t attr;
// Socket creation for UDP
acceptSocket = socket(AF_INET,SOCK_DGRAM,0);
if(acceptSocket == -1)
{
printf("Failure: socket creation is failed, failure code\n");
return 1;
}
else
{
printf("Socket started!\n");
}
memset(&addr, 0, sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
rc=bind(acceptSocket,(struct sockaddr*)&addr,sizeof(addr));
fcntl(acceptSocket, O_NONBLOCK);
if(rc== -1)
{
printf("Oh dear, something went wrong with bind()! %s\n", strerror(errno));
return -1;
}
else
{
printf("Socket an port %d \n",port);
}
return acceptSocket;
}
int create_timer (void)
{
timer_t timer_id;
int timerfd = timer_create (CLOCK_REALTIME, 0, &timer_id);
if (timerfd < 0) {
perror ("timerfd_create:");
return -1;
}
return timerfd;
}
int start_timer_msec (int fd, int msec)
{
struct itimerspec timspec;
memset (&timspec, 0, sizeof(timspec));
timspec.it_value.tv_sec = 0;
timspec.it_value.tv_nsec = msec * 1000 * 1000;
if (timer_settime(fd, 0, &timspec, NULL) < 0) {
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
Xcp_Initialize();
int fd_2ms = create_timer();
int fd_10ms = create_timer();
int fd_100ms = create_timer();
int rval = 0;
if ((fd_2ms < 0) || (fd_10ms < 0) || (fd_100ms < 0)) {
exit (1);
}
if ((sock = CreateSocket()) < 0) {
perror ("Create_socket");
// fclose (fp);
exit (1);
}
start_timer_msec (fd_2ms, 2);
start_timer_msec (fd_10ms, 10);
start_timer_msec (fd_100ms, 100);
do
{
socklen_t len;
int max_fd = 0;
fd_set rdfds;
FD_ZERO (&rdfds);
GET_MAX_FD (max_fd, sock);
FD_SET (sock, &rdfds);
GET_MAX_FD (max_fd, fd_2ms);
FD_SET (fd_2ms, &rdfds);
GET_MAX_FD (max_fd, fd_10ms);
FD_SET (fd_10ms, &rdfds);
GET_MAX_FD (max_fd, fd_100ms);
FD_SET (fd_100ms, &rdfds);
rval = select (max_fd, &rdfds, NULL, NULL, NULL);
if (rval < 0) {
if (errno == EINTR)
continue;
} else if (rval > 0) {
/*Process CLI*/
if ((FD_ISSET (sock, &rdfds)))
{
FD_CLR(sock, &rdfds);
len = sizeof(client);
printf("NEW DATA ARRIVED\n");
//non blocking mode : MSG_DONTWAIT
rc=recvfrom(sock, buf, 256, 0, (struct sockaddr*) &client, &len);
//I am calculating the time here
//InterruptTime = GetTimeStamp();
//measurements[17] = InterruptTime;
if(rc==0)
{
printf("Server has no connection..\n");
break;
}
if(rc==-1)
{
if (errno == SIGINT)
continue;
printf("Oh dear, something went wrong with read()! %s\n", strerror(errno));
break;
}
ConfigureISR( );
XcpIp_RxCallback( (uint16) rc, (uint8*) buf, (uint16) port );
}
if ((FD_ISSET (fd_2ms, &rdfds))) {
FD_CLR(fd_2ms, &rdfds);
TASK1(Task2ms_Raster);
start_timer_msec (fd_2ms, 2);
}
if ((FD_ISSET (fd_10ms, &rdfds))) {
FD_CLR(fd_10ms, &rdfds);
TASK2(Task10ms_Raster);
start_timer_msec (fd_10ms, 10);
}
if ((FD_ISSET (fd_100ms, &rdfds))) {
FD_CLR(fd_100ms, &rdfds);
TASK3(Task100ms_Raster);
start_timer_msec (fd_100ms, 100);
}
}
} while (1);
close(sock);
//fclose (fp);
return 0;
}
I created a socket to receive data from client via the ip address and port number. I created a timer to call the task for every 2ms, 10ms and 100ms. The above code is working fine for linux. But how to convert the above code for QNX RTOS. What are the changes should I make for QNX rtos. could some one please help me ??
IF I use the same code in qnx then it is crashing at int fd_2ms = create_timer(); !!

Sending data to multiple clients connected on my Server

I have this server app where clients can connect to. Now i want that when the clients are connected i can send data to all of them. I manage to do it when i connect my two clients.. what i send is received by my two clients. but my problem is when i connect client1 then send data to server, client1 can receive data then i connect client2 and i send data to the server. now when i send data from server to my clients only client1 can receive data but when i disconnect client 1 then client2 can receive data from the server.
How can i make them work at the same time?.. Also how can i make my server accept messages at the same time from my client?..
Here's the part of the code im having trouble.
for(j=0;j<MAX_CLIENTS; j++)
Clients[j].connected_sock = -1;
do
{
fduse = fdin;
printf("Waiting for Connection\n");
err = select(sMax + 1, &fduse, NULL, NULL, NULL);
if (err < 0)
{
perror(" select() failed");
break;
}
DescRead = err;
for (SockStorage=0; SockStorage <= sMax && DescRead > 0; ++SockStorage)
{
if (FD_ISSET(SockStorage, &fduse))
{
DescRead -= 1;
if (SockStorage == socketFd)
{
printf(" Listening socket is readable\n");
do
{
NewSFD = accept(socketFd,(struct sockaddr *) &cli_addr, &clilen);
if (NewSFD < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" accept() failed");
DCSERVER = TRUE;
}
break;
}
if(ClientCount < MAX_CLIENTS){
for(loop = 0; loop <MAX_CLIENTS; loop++){
if(Clients[loop].connected_sock<0){
Clients[loop].connected_sock = NewSFD;
break;
}
}
ClientCount++;
}
else
{
printf("Maximum Client Reached.\n");
char *sendtoclient = "Server full. ";
send(NewSFD, sendtoclient, strlen(sendtoclient),0);
close(NewSFD);
break;
}
ip = ntohl(cli_addr.sin_addr.s_addr);
printf(" Connection from %d.%d.%d.%d\n",
(int)(ip>>24)&0xff,
(int)(ip>>16)&0xff,
(int)(ip>>8)&0xff,
(int)(ip>>0)&0xff);
dlogs(ip);
FD_SET(NewSFD, &fdin);
if (NewSFD > sMax)
sMax = NewSFD;
} while (NewSFD != -1);
}
else
{
int d;
for(d=0; d<MAX_CLIENTS; d++){
printf("Descriptor ID: %d\n", Clients[d].connected_sock);
}
pfds[0].fd = fd;
pfds[0].events = POLLIN;
pfds[1].fd = SockStorage;
pfds[1].events = POLLIN;
state = FALSE;
do
{
rc = poll(pfds, 2, -1);
if (pfds[0].revents & POLLIN)
{
while ((nbytes = read(fd, buf, sizeof(buf)-1)) > 0)
{
buf[nbytes] = '\0';
printf("%s\n", buf);
}
pfds[0].events = 0;
pfds[1].events = POLLIN | POLLOUT;
}
if (pfds[1].revents & POLLIN)
{
err = recv(SockStorage, strbuf, sizeof(strbuf), 0);
if (err < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" recv() failed");
state = TRUE;
}
break;
}
if (err == 0)
{
printf(" Connection closed\n");
state = TRUE;
break;
}
dSize = err;
printf(" %d bytes received\n", dSize);
}
if (pfds[1].revents & POLLOUT)
{
int s;
for(s=0; s<MAX_CLIENTS; s++){
if(Clients[s].connected_sock>0){
err = send(Clients[s].connected_sock, buf, strlen(buf), 0);
if (err < 0)
{
perror(" send() failed");
state = TRUE;
break;
}
}
}
pfds[0].events = POLLIN;
pfds[1].events = POLLIN;
}
} while (TRUE);
Here's how im sending data to my clients.
int s;
for(s=0; s<MAX_CLIENTS; s++){
if(Clients[s].connected_sock>0){
err = send(Clients[s].connected_sock, buf, strlen(buf), 0);
if (err < 0)
{
perror(" send() failed");
state = TRUE;
break;
}
}
}
Thanks,
There are generally couple of possible solutions:
You can use separate threads for each client connection;
You can use select;
You can use poll;
You can use epoll;
In Windows environment there are also some other possibilities like IOCP for example.
Each of mentioned solutions have some pros and cons (you need generally distinguish between simplicity and performance).
You can read some network programming tutorial for more details, e.g. this.

Resources