• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
netpumber

Async Chat server/client suggestions and hints.

14 posts in this topic

Hello.

So a month now im searching in net different methods to create a chat client/server app.
Clients will connect to the server and the server will send the message of each client to the rest.
I use C and Visual studio 10 and finally i decided to use the async method.
My app will be a simple console application so i will use WSAEventSelect instead of WSAAsyncSelect.

I have found only [url="http://www.codeproject.com/KB/IP/networkevents.aspx"]this[/url] tutorial on net talking about this.

Also i read and for IOCP but my knowledge is not enough for something like this.

I ask you to tell me if you find my decision correct and if you have any tutorial or post on mind that can help me. Please let me know.

Also any hint or suggestion is welcomed.

Thanks in advance.
0

Share this post


Link to post
Share on other sites
It seems like several entries in the FAQ would cover this. Have you read the FAQ thoroughly and read the documents it links to?


Chat is no different than any other message; it happens to have text that you display, but that kind of network message is no different than a message about updating units or updating player stats or transmitting a VoIP message. It is just a block of data meant for direct display to the human.
0

Share this post


Link to post
Share on other sites
Yeah ok i ve read the [url="http://www.gamedev.net/index.php?app=forums&module=forums&section=rules&f=15"]FAQ[/url] but it talks mostly for select() method as i saw.
The truth is that i have try the select method but there was a problem with the message send time.

Here is my code for my select() try.

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.
...[/code]


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
....[/code]



and here is the image that shows the message transfer delay.

[img]http://img402.imageshack.us/img402/6692/chatbq.png[/img]

After these problems i decided to use the WSAEventSelect with event creation and blah blah as the tutorial posted before says..
0

Share this post


Link to post
Share on other sites
[quote]
[code]
// Setup timer.
timeout.tv_sec = 2;
timeout.tv_usec = 5000;
[/code]
[/quote]

This timeout specifies 2.005 seconds -- two seconds, and five thousand microseconds. Perhaps this is what you intend, but I think it's not.
Generally, when polling the network together with a game or event loop, you want to set tv_sec and tv_usec both to 0.

[quote]
[code]
for(i=0;i<=maxDescriptor;i++)
{
if(FD_ISSET(i,&BackUpfdread))

[/code]
[/quote]

This doesn't work well at all in Windows. sockets are handles, which can have very high values. "maxDescriptor" is ignored on input. You should test the values you know you have (the listening socket, and each client socket) rather than "all integers." You're basically testing ALMOST ALL INTEGERS to see if one of them happens to match a handle value stored in the FD_SET. That is one cause of performance problems.

[quote]
[code]
// Receiving the username from the new client.
memset(username,0,sizeof(username));
recv(AcceptSocket,username,sizeof(username),0);
[/code]
[/quote]

Someone can block your game forever by doing telnet to your server, and then not sending a username. Never recv from a socket unless select() tells you it won't block.

[quote]
[code]
RecvBytes = recv(i, RecvBuff, sizeof(RecvBuff)-1, 0);
[/code]
[/quote]

See above -- "i" is generally not a valid socket handle value.

[quote]
After these problems i decided to use the WSAEventSelect with event creation and blah blah as the tutorial posted before says..
[/quote]

WSAEventSelect is only slightly less bad than WSAAsyncSelect. Use select(), or use OVERLAPPED I/O on sockets as handles.
Note that, apart from scanning all integers, other performance problems with your test may be that there is not enough CPU to handle all the clients+server you're running, so Windows will time slice, and also you're not using TCP_NODELAY, so sends will be delayed by several hundred milliseconds.
2

Share this post


Link to post
Share on other sites
Thanks a lot for your answer hplus0603 .

First of all i think that the second problem you referred to, will be solved using a struct that will save the socket number of each client and in the for loop i will use these numbers.

As for the username sending i will find another way to do this.

Finally i want you to tell me why to use select() and not WSAEventSelect method.
As i read on net the first one uses more CPU than the other.
[u] [/u]
0

Share this post


Link to post
Share on other sites
[quote name='netpumber' timestamp='1324641936' post='4896797']
Finally i want you to tell me why to use select() and not WSAEventSelect method.
As i read on net the first one uses more CPU than the other.
[u] [/u][/quote]

WASEventSelect() has an inherent race condition that is very hard to work around. If you read about it on MSDN, they talk about it, but don't actually explain the systems programming aspects. And yet, it's not very scalable -- the NT kernel can wait on at most 64 events at the same time (using MsgWaitForMultipleObjectsEx()).

If you want simple to code, use select() -- it will work fine for dozens of connections.

If you want high performance, use OVERLAPPED I/O on sockets with I/O completion ports -- or use boost::asio, which puts a slightly nicer interface on top of that, plus is portable across operating systems.
0

Share this post


Link to post
Share on other sites
[quote name='hplus0603' timestamp='1324602493' post='4896692']
[quote]
[code]
for(i=0;i<=maxDescriptor;i++)
{
if(FD_ISSET(i,&BackUpfdread))

[/code]
[/quote]

This doesn't work well at all in Windows. sockets are handles, which can have very high values. "maxDescriptor" is ignored on input. You should test the values you know you have (the listening socket, and each client socket) rather than "all integers." You're basically testing ALMOST ALL INTEGERS to see if one of them happens to match a handle value stored in the FD_SET. That is one cause of performance problems.
[/quote]

I had something like that and changed it to as follows. I didn't do any measurements, but thought there was a noticeable improvement in the performance from the change. I count down rather than starting at zero and counting up. Also the code with the selrc is used to shorten this potentially long loop. selrc is the return code from select. After addressing all of the events, we can skip the rest of the loop.

[code]
for (int32_t sock = fdmax; sock > 0; --sock) {
if (FD_ISSET(sock, &read_fds)) {
if (mediateRequest(sock)) {
FD_SET(cmwSendbuf.sock_, &masterwrite);
} else {
closeSocket(sock);
FD_CLR(sock, &master);
}
if (0 == --selrc) break;
}
}
[/code]


Brian Wood
Ebenezer Enterprises
[url="http://webebenezer.net/"]http://webEbenezer.net[/url]
0

Share this post


Link to post
Share on other sites
[quote name='hplus0603' timestamp='1324663713' post='4896875']
[quote name='netpumber' timestamp='1324641936' post='4896797']
Finally i want you to tell me why to use select() and not WSAEventSelect method.
As i read on net the first one uses more CPU than the other.
[u] [/u][/quote]

WASEventSelect() has an inherent race condition that is very hard to work around. If you read about it on MSDN, they talk about it, but don't actually explain the systems programming aspects. And yet, it's not very scalable -- the NT kernel can wait on at most 64 events at the same time (using MsgWaitForMultipleObjectsEx()).

If you want simple to code, use select() -- it will work fine for dozens of connections.
[/quote]

I like select's portability and not having to depend on a large library which itself depends on a number of other libraries. (I don't use select in the C++ Middleware Writer, but portability isn't an issue there.)

Brian Wood
Ebenezer Enterprises
[url="http://webEbenezer.net"]http://webEbenezer.net[/url]
0

Share this post


Link to post
Share on other sites
[quote name='wood_brian' timestamp='1324676579' post='4896928'][quote name='hplus0603' timestamp='1324602493' post='4896692'][quote]
[code]
for(i=0;i<=maxDescriptor;i++)
{
if(FD_ISSET(i,&BackUpfdread))

[/code]
[/quote]This doesn't work well at all in Windows. sockets are handles, which can have very high values. "maxDescriptor" is ignored on input. You should test the values you know you have (the listening socket, and each client socket) rather than "all integers." You're basically testing ALMOST ALL INTEGERS to see if one of them happens to match a handle value stored in the FD_SET. That is one cause of performance problems.
[/quote]I had something like that and changed it to as follows. I didn't do any measurements, but thought there was a noticeable improvement in the performance from the change.
[code]
for (int32_t sock = fdmax; sock > 0; --sock) {
if (FD_ISSET(sock, &read_fds)) {
[/code]
[/quote]
That suffers from exactly the same problem.

You are not iterating over your handles in either examples.

Instead you are iterating over potentially billions of integers where by brute force it will eventually stumble over your handle.


Keep a separate list of handles and only iterate over those. For example, you may have:

[code]
typedef std::vector<int32_t> HandleCollection;
...
HandleCollection openHandles;
...

// add an incoming connection
AcceptSocket = accept(ListeningSocket,(SOCKADDR *)&ClientAddr,&ClientAddrSize);
openHandles.push_back(AcceptSocket);
...
for(HandleCollection::iterator it = openHandles.begin(); it!=openhandles.end(); ++it;)
{
if (FD_ISSET(*it, &read_fds)) {
...
[/code]
This will reduce it from attempting to check against potentially billions of non-handles to instead just checking against the small number of actual handles you know to be open.

In practice you will likely want to store more than just an integer. Eventually you will want a structure or class with additional information about each client, but that is a future exercise.
1

Share this post


Link to post
Share on other sites
Hello again.

After our conversation here i decide to give a try once again with select method.
Here is the new code.
I put 0 in timeout and also i use an array with sockets to avoid looping between all these integers.

Server:

[code]
#include <WinSock2.h>
#include <stdio.h>
#include <time.h>



main()
{

SOCKET ListeningSocket;
SOCKET AcceptSocket;

SOCKADDR_IN ServerAddr;
SOCKADDR_IN ClientAddr;

WSADATA wsaData;

const unsigned short PORT = 4444;

FD_SET fdread;
FD_SET BackUpfdread;
FD_SET fdwrite;
FD_SET BackUpfdwrite;

int maxDescriptor;
SOCKET SocketArray[20];
int index = 0;
int selectResults;
int i,k;
int clientAddrSize;
int RecvBytes;
int SentBytes;

char SentBuff[500];
char RecvBuff[500];

struct timeval timeout;

// Initialize Winsock2.2
WSAStartup(MAKEWORD(2,2),&wsaData);

// Initialize Listening Socket
ListeningSocket = socket(AF_INET,SOCK_STREAM,0);

// Initialize ServerAddr
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
ServerAddr.sin_port = htons(PORT);

// Bind the ServerAddr with ListeningSocket
bind(ListeningSocket,(SOCKADDR *)&ServerAddr,sizeof(ServerAddr));

// Listening Socket
listen(ListeningSocket,5);

FD_ZERO(&fdread);
FD_ZERO(&BackUpfdread);
FD_ZERO(&fdwrite);
FD_ZERO(&BackUpfdwrite);

// Asign ListeningSocket at fdread
FD_SET(ListeningSocket,&fdread);

maxDescriptor = ListeningSocket;

SocketArray[index] = ListeningSocket;
index++;

timeout.tv_sec = 0;
timeout.tv_usec = 0;

// Main loop starts here
for(; ;)
{

BackUpfdread = fdread;
BackUpfdwrite = fdwrite;
selectResults = select(maxDescriptor+1,&BackUpfdread,&BackUpfdwrite,NULL,&timeout);
//printf("server select() OK\n");

if(selectResults == -1)
{
printf("Select() error");
WSACleanup();
return 0;
}


for(i=0;i<=index-1;i++)
{
//printf("%d\n",SocketArray[i]);
if(FD_ISSET(SocketArray[i],&BackUpfdread))
{
if(SocketArray[i] == ListeningSocket) // we have a new connection
{
clientAddrSize = sizeof(ClientAddr);
AcceptSocket = accept(ListeningSocket,(SOCKADDR *)&ClientAddr,&clientAddrSize);

// Add the newest accepted socket to the fdread and fdwrite sets.
FD_SET(AcceptSocket,&fdread);
FD_SET(AcceptSocket,&fdwrite);

// Add the newest accepted socket into SocketArray
SocketArray[index] = AcceptSocket;
index++;

// keep track of the maxDescriptor.
if(AcceptSocket > maxDescriptor)
{
maxDescriptor = AcceptSocket;
}

printf("New connection from %s on socket %d\n", inet_ntoa(ClientAddr.sin_addr), AcceptSocket);

}else{ // That means that the socket is not from a new conection and has something sent.

memset(RecvBuff,0,sizeof(RecvBuff));
RecvBytes = recv(SocketArray[i], RecvBuff, sizeof(RecvBuff)-1, 0);

if(RecvBytes > 0) // Some data received.
{

printf("Message Send.\n");
printf("Message was: %s\n",RecvBuff);

for(k=0;k<=index-1;k++)
{
if(FD_ISSET(SocketArray[k],&BackUpfdwrite))
{
if(SocketArray[k] != ListeningSocket && SocketArray[k] != SocketArray[i])
{
memset(SentBuff,0,sizeof(SentBuff));
strcpy(SentBuff,RecvBuff);
SentBytes = send(SocketArray[k],SentBuff,sizeof(SentBuff),0);

}

}
}

}

}

}
}


}// Main loop ends here


}[/code]


Client:

[code]#include <WinSock2.h>
#include <stdio.h>
#include <time.h>



main()
{

SOCKET ConnectSocket;
SOCKET SocketArray[20];

SOCKADDR_IN ServerAddr;

WSADATA wsaData;

FD_SET fdwrite;
FD_SET fdread;
FD_SET BackUpfdread;
FD_SET BackUpfdwrite;

char server_address[20] = "192.168.1.4";
char SentBuff[500];
char RecvBuff[500];

const unsigned short PORT = 4444;

int maxDescriptor;
int index = 0;
int SelectResults;
int i;
int RecvBytes;
int SentBytes;

struct timeval timeout;


// Initialize Winsock 2.2
WSAStartup(MAKEWORD(2,2),&wsaData);

// Initialize ServerAddr
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.s_addr = inet_addr(server_address);
ServerAddr.sin_port = htons(PORT);

// Create a new socket to make a client connection.
ConnectSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

// Clear the fd sets
FD_ZERO(&fdread);
FD_ZERO(&BackUpfdread);
FD_ZERO(&fdwrite);
FD_ZERO(&BackUpfdwrite);

// Asign ConnectSocket into fdread and fdwrite.
FD_SET(ConnectSocket,&fdread);
FD_SET(ConnectSocket,&fdwrite);

// Set timer
timeout.tv_sec = 0;
timeout.tv_usec = 0;

maxDescriptor = ConnectSocket;
SocketArray[index] = ConnectSocket;
index++;

// Make a connection to the server with socket s.
if(connect(ConnectSocket, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR)
{
printf("Couldn't connect to the server\n");
}

// Main loop starts here
for(; ;)
{
BackUpfdread = fdread;
BackUpfdwrite = fdwrite;

memset(SentBuff, 0, sizeof(SentBuff));
printf("Write: ");
gets_s(SentBuff, sizeof(SentBuff));

SelectResults = select(maxDescriptor+1,&BackUpfdread,&BackUpfdwrite,NULL,&timeout);

for(i=0;i<=index-1;i++)
{
// Something to read from server.
if(FD_ISSET(SocketArray[i],&BackUpfdread) && SocketArray[i] == ConnectSocket)
{
RecvBytes = recv(SocketArray[i], RecvBuff, sizeof(RecvBuff), 0);

if(RecvBytes > 0)
{
printf("%s\n",RecvBuff);
// Cleaning the Receive Buffer
memset(RecvBuff,0,sizeof(RecvBuff));
}

}

// Something to write.
if(FD_ISSET(SocketArray[i],&BackUpfdwrite) && SocketArray[i] == ConnectSocket)
{
SentBytes = send(SocketArray[i], SentBuff,sizeof(SentBuff),0);
// Cleaning the Sent Buffer
memset(SentBuff,0,sizeof(SentBuff));

}


}

} // Main menu ends here

}[/code]


The problem is that i ve noticed that still there is a delay on message transfer. It looks like there are blocking sockets.
Here is a pic.

[img]http://img515.imageshack.us/img515/3237/64047117.png[/img]
0

Share this post


Link to post
Share on other sites
[quote name='wood_brian' timestamp='1324676579' post='4896928']
[quote name='hplus0603' timestamp='1324602493' post='4896692']
[quote]
[code]
for(i=0;i<=maxDescriptor;i++)
{
if(FD_ISSET(i,&BackUpfdread))

[/code]
[/quote]

This doesn't work well at all in Windows. sockets are handles, which can have very high values. "maxDescriptor" is ignored on input. You should test the values you know you have (the listening socket, and each client socket) rather than "all integers." You're basically testing ALMOST ALL INTEGERS to see if one of them happens to match a handle value stored in the FD_SET. That is one cause of performance problems.
[/quote]

I had something like that and changed it to as follows. I didn't do any measurements, but thought there was a noticeable improvement in the performance from the change. I count down rather than starting at zero and counting up. Also the code with the selrc is used to shorten this potentially long loop. selrc is the return code from select. After addressing all of the events, we can skip the rest of the loop.

[code]
for (int32_t sock = fdmax; sock > 0; --sock) {
if (FD_ISSET(sock, &read_fds)) {
if (mediateRequest(sock)) {
FD_SET(cmwSendbuf.sock_, &masterwrite);
} else {
closeSocket(sock);
FD_CLR(sock, &master);
}
if (0 == --selrc) break;
}
}
[/code]


Brian Wood
Ebenezer Enterprises
[url="http://webebenezer.net/"]http://webEbenezer.net[/url]
[/quote]

That is just as bad. You want to only test the actual file descriptors that you have. Keep all user connections in an array or list or hash table, and iterate over that, testing if each users' socket is in the active set. Anything else is too sloppy for code you intend to keep.

Really, your code is similar in essence to this code:

[code]
int calculate_sum(int a, int b) {
for (int i = MAX_INT; i > MIN_INT; --i) {
if (i - b == a) {
return i;
}
}
return MIN_INT;
}
[/code]
0

Share this post


Link to post
Share on other sites
[quote name='hplus0603' timestamp='1324777580' post='4897194']
That is just as bad. You want to only test the actual file descriptors that you have. Keep all user connections in an array or list or hash table, and iterate over that, testing if each users' socket is in the active set. Anything else is too sloppy for code you intend to keep.

[/quote]

I decided to try an implementation like that and was surprised by how it turned out. It added more than 5 lines to the code and more than 2,000 bytes to the executable. At run time it also needs the memory management of the list or vector. ( I used a vector. A list would be a poor choice here I think.) The idea may still be useful, but wish it were cleaner.

Brian Wood
Ebenezer Enterprises
[url="http://webEbenezer.net"]http://webEbenezer.net[/url]
0

Share this post


Link to post
Share on other sites
So.. whats the problem with my new select() application ? Why the delay still exists ?
Can anyone think something ?
0

Share this post


Link to post
Share on other sites
Did you turn on TCP_NODELAY?
Did you add a SleepEx(10, FALSE) inside your main loop on both client and server, to allow scheduling?
0

Share this post


Link to post
Share on other sites
i should turn on TCP_NODELAY only to the client or in the server too ?

Edit:

I have made these changes in client

[CODE]// Create a new socket to make a client connection.
[b]BOOL bOpt = TRUE;[/b]
ConnectSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
[b]setsockopt(ConnectSocket, IPPROTO_TCP, TCP_NODELAY,(char*)&bOpt,sizeof(BOOL));[/b][/CODE]


and before main loop ends in both (client & server)

[CODE] }

[b]SleepEx(10, FALSE);[/b]
} // Main menu ends here[/CODE]

The results still the same. Edited by netpumber
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0