Hi.
I have wrote this simple client-server application for chat reason.
Both server and client uses the select() method.
Here is a part from the code of server :
Code:
....
// Listening
//iMode = 1; // If iMode!=0, non-blocking mode is enabled.
listen(ListeningSocket,5);
//ioctlsocket(ListeningSocket,FIONBIO,&iMode); // Enable the non-locking mode.
// Clear the two fd sets
FD_ZERO(&fdread);
FD_ZERO(&BackUpfdread);
FD_ZERO(&fdwrite);
FD_ZERO(&BackUpfdwrite);
// Asign the ListeningSocket with fdread.
FD_SET(ListeningSocket,&fdread);
FD_SET(ListeningSocket,&fdwrite);
// Set as maxDescriptor ListeningSocket.
maxDescriptor = ListeningSocket;
// Setup timer.
timeout.tv_sec = 2;
timeout.tv_usec = 5000;
// Main loop starts here.
for(; ;)
{
// Keep a backup of FD set cause select() erases it, if there's nothing to do.
BackUpfdread = fdread;
BackUpfdwrite = fdwrite;
selectResults = select(maxDescriptor+1,&BackUpfdread,&BackUpfdwrite,NULL,&timeout);
if(selectResults == -1)
{
printf("Select() error");
WSACleanup();
return 0;
}
// Check the fdread set for alive connections
for(i=0;i<=maxDescriptor;i++)
{
if(FD_ISSET(i,&BackUpfdread))
{
if(i == ListeningSocket) // That means we have a NEW CONNECTION and must hadle it.
{
ClientAddrSize = sizeof(ClientAddr);
AcceptSocket = accept(ListeningSocket,(SOCKADDR *)&ClientAddr,&ClientAddrSize);
if(AcceptSocket == -1)
{
printf("Winsock error - Unable to accept socket");
WSACleanup();
return 0;
}
// Add the newest socket in the fdread set.
FD_SET(AcceptSocket,&fdread);
FD_SET(AcceptSocket,&fdwrite);
// Keep track of the maxDescriptor.
if(AcceptSocket > maxDescriptor)
{
maxDescriptor = AcceptSocket;
}
// Receiving the username from the new client.
memset(username,0,sizeof(username));
recv(AcceptSocket,username,sizeof(username),0);
printf("New connection (username: %s) from %s on socket %d\n", username, inet_ntoa(ClientAddr.sin_addr), AcceptSocket);
// Send Welcome Message.
send(AcceptSocket,msg,sizeof(msg),0);
}else{ // That means that the socket (i) isn't from a new connection and has something sent.
RecvBytes = recv(i, RecvBuff, sizeof(RecvBuff)-1, 0);
if(RecvBytes == -1)
{
printf("Winsock error - Cannot receive data from client");
WSACleanup();
return 0;
}
if(RecvBytes == 0)
{
printf("Socket %d hung up\n", i);
// Shutdown Socket
shutdown(i,SD_RECEIVE);
// Clear fdread.
FD_CLR(i, &fdread);
}
if(RecvBytes > 0)
{
printf("Message Send.\n");
printf("Message was: %s\n",RecvBuff);
for(k=0;k<=maxDescriptor;k++)
{
if(FD_ISSET(k,&BackUpfdwrite))
{
memset(SentBuff,0,sizeof(SentBuff));
strcpy(SentBuff,RecvBuff);
SentBytes = send(k,SentBuff,sizeof(SentBuff),0);
}
}
}
}
}
}
} // Main loop ends here.
...
and a code part from client
Code:
....
// Initialize Winshock 2.2
WSAStartup(MAKEWORD(2,2),&wsaData);
// Create a new socket to make a client connection.
ConnectSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
// Initialize Servers SOCKADDR_IN
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(port);
ServerAddr.sin_addr.s_addr = inet_addr(server_address);
// Clear the fd sets
FD_ZERO(&fdread);
FD_ZERO(&BackUpfdread);
FD_ZERO(&fdwrite);
FD_ZERO(&BackUpfdwrite);
// Asign the ListeningSocket with fdread and fdwrite.
FD_SET(ConnectSocket,&fdread);
FD_SET(ConnectSocket,&fdwrite);
// Set as maxDescriptor ListeningSocket.
maxDescriptor = ConnectSocket;
// Setup timer.
timer.tv_sec = 2;
timer.tv_usec = 5000;
//iMode = 1; // If iMode!=0, non-blocking mode is enabled.
//ioctlsocket(ConnectSocket,FIONBIO,&iMode); // Enable the non-locking mode.
// Make a connection to the server with socket s.
connect(ConnectSocket, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr));
// Send the username to server.
send(ConnectSocket,username,strlen(username),0);
// Receive Welcome Message From Server (If any..)
RecvBytes = recv(ConnectSocket,RecvBuff,sizeof(RecvBuff),0);
if(RecvBytes > 0)
{
printf("%s",RecvBuff);
// Cleaning the Receive Buffer
memset(RecvBuff,0,sizeof(RecvBuff));
}
// Main loop starts here
for(; ;)
{
// Copy the fdread into BackUpfdread and fdwrite to BackUpfdwrite.
BackUpfdread = fdread;
BackUpfdwrite = fdwrite;
SelectResults = select(maxDescriptor+1,&BackUpfdread,&BackUpfdwrite,NULL,&timer);
if(SelectResults == -1)
{
perror("Client-select() error!\n");
exit(1);
}
//printf("Client-select is OK\n");
//Check if we have some data to read.
if (FD_ISSET(ConnectSocket, &BackUpfdread))
{
RecvBytes = recv(ConnectSocket, RecvBuff, sizeof(RecvBuff), 0);
if(RecvBytes > 0)
{
printf("%s\n",RecvBuff);
// Cleaning the Receive Buffer
memset(RecvBuff,0,sizeof(RecvBuff));
}
}
memset(SentBuff, 0, sizeof(SentBuff));
printf("Write: ");
gets_s(SentBuff, sizeof(SentBuff));
//Check if we have some data to write.
if (FD_ISSET(ConnectSocket, &BackUpfdwrite))
{
SentBytes = send(ConnectSocket, SentBuff,sizeof(SentBuff),0);
// Cleaning the Sent Buffer
memset(SentBuff,0,sizeof(SentBuff));
}
} // Main loop ends here
....
the problem is that the messages didn't arrive on time to the clients. Here is what happens in images
http://img402.imageshack.us/img402/6692/chatbq.png
I want your opinion on how to fix this problem. Any advice welcomed.
Thanks for your time.