Yeah...I know this has been talked about before, but the examples I saw used a diffrent method of storing connected clients, so I failed trying to convert their examples. But basicly I need to find a way to send a message to everyone once the server has recieved it. I know the other examples I saw used array's to store clients while this programs uses a set. I know that somehow I have to run through the set, sending a message to all the clients listed, using a loop. But I am not toally sure how that is done.

I got most of this code off a tutorial that I am reading but I have edited to my liking and purpose

09-23-2004

codec

an fd_set is generally only used to pass the sockets you wish to check for readability/writability to select()

It's not a good idea to use an fd_set to store your actual list of connected clients because when you pass the fd_set to select() it's contents is modified to only contain the sockets which have data waiting (readability) or are able to accept data (writability). Normally you'd construct your fd_set from your list of clients before you call select(), or as you've done, construct a 'master' fd_set from which you create a temporary fd_set for select() to work with each loop.

There's many different ways to store your connected clients list, depending on how you choose to design your server, but if you're just writing a program to experiment, i'd say just have an array of sockets of a fixed size (which can then be your max number clients), to keep it simple. It would also be possible to use your masterSet fd_set as a list of your connected clients I think, and loop through that, although I haven't ever tried to do that. I'd recommend having a seperate list of connections.

you want to pass a reference to somewhere it can store the recieved data (param 2) and the size of the array that it can fill with the data.

I'll have a good look through when I have a bit more time. Haven't done any sockets programming for a while so I need a bit of a refresher myself... :)

Hope that helps for now.

Dan

09-23-2004

codec

One other error I just spotted

Remember 'FD_SET' is a macro for adding sockets to an fd_set and 'fd_set' is the actual structure for an fd_set.

So you'd want to declare your fd_sets like so:

fd_set masterSet;
fd_set pollingSet = masterSet;

(notice no caps)

09-23-2004

mill1k

Quote:

Originally Posted by codec

an fd_set is generally only used to pass the sockets you wish to check for readability/writability to select()

It's not a good idea to use an fd_set to store your actual list of connected clients because when you pass the fd_set to select() it's contents is modified to only contain the sockets which have data waiting (readability) or are able to accept data (writability). Normally you'd construct your fd_set from your list of clients before you call select(), or as you've done, construct a 'master' fd_set from which you create a temporary fd_set for select() to work with each loop.

There's many different ways to store your connected clients list, depending on how you choose to design your server, but if you're just writing a program to experiment, i'd say just have an array of sockets of a fixed size (which can then be your max number clients), to keep it simple. It would also be possible to use your masterSet fd_set as a list of your connected clients I think, and loop through that, although I haven't ever tried to do that. I'd recommend having a seperate list of connections.

that snippet of code is used becasue the client and server can send messages of variable size. And i dont think that the code you sugested can do that. Basicly the program recives the size then it acctually sends the message

that snippet of code is used becasue the client and server can send messages of variable size. And i dont think that the code you sugested can do that. Basicly the program recives the size then it acctually sends the message

If you're trying to store the size of the recieved data in messagesize, I'm pretty sure it's not going to do that. If it does it's a very strange and not necessarily reliable way. It'll fill numbytes with the amount of data recieved (unless the remote closes the connection or there's an error, which you already handle) so you don't need to use two calls to recv(), just the one that I suggested and use numbytes as your messagesize.

After looking at your code more closely I see that you do actually get the data at a later stage. Only had a chance to have a quick look earlier and your code isn't the most readable ever.

The information I gave you earlier is still useful for your original problem however. Had any luck?

09-26-2004

mill1k

I turns out that it does use a array to store the clients, so I tried a snippet of code that ran through the entire array looking for clients to send to.

After thinking about it at work I reliezed a problem. The clients can't recieve unless they send..so it looks like i am going to need to find a threading tutorial so i can create a recieving thread.

09-27-2004

codec

If you want your server to send out whatever it recieves from one client to every client then loop through your master fd_set and not the polling set as the contents of this would have been modified by the select() function call to contain only the sockets whcih having data waiting.

09-28-2004

codec

Also, if designed correctly, a server app using the select() function that is as simple as you're doing shouldn't need any extra threads at all. You can do away with the accept thread by adding your listening socket to your fd_set you pass to select(), then whenever a connection is waiting on your listening socket select() will let you know.

[edit] You can use this FD_ISSET() macro to check to see if it's your listening socket that's got a connection waiting [/edit]

All this information, and loads more can be obtained just by looking the the MSDN Winsock 2 section.

09-29-2004

Hunter2

>>If you're trying to store the size of the recieved data in messagesize, I'm pretty sure it's not going to do that. If it does it's a very strange and not necessarily reliable way.
I'd just like to point out that this is a perfectly valid way of sending and receiving data. &messagesize is a pointer to the beginning of the memory which holds the value of messagesize, which is really just a string of bytes. By converting it to char*, it becomes a valid memory address for use with recv(), and recv() simply interprets it as an array of char - an array of _bytes_ (actually unsigned char is the only true byte, but for our purposes char works too). So it receives the bytes from the server and writes them into messagesize's memory location, and thus you have just received binary data directly into the desired variable.

Also note, recv() isn't guaranteed to receive the whole packet in one call... you might only receive 2 bytes or 1, in which case it's your responsibility to make sure that you get the rest of the packet later.

09-30-2004

codec

Quote:

Originally Posted by Hunter2

>>If you're trying to store the size of the recieved data in messagesize, I'm pretty sure it's not going to do that. If it does it's a very strange and not necessarily reliable way.
I'd just like to point out that this is a perfectly valid way of sending and receiving data. &messagesize is a pointer to the beginning of the memory which holds the value of messagesize, which is really just a string of bytes. By converting it to char*, it becomes a valid memory address for use with recv(), and recv() simply interprets it as an array of char - an array of _bytes_ (actually unsigned char is the only true byte, but for our purposes char works too). So it receives the bytes from the server and writes them into messagesize's memory location, and thus you have just received binary data directly into the desired variable.

That's easy to point out when you have the benefit of seeing all the relevant code I did not. Without seeing the client-side code, it was not possible to know he'd included the messagesize in his packet. Looking at the code on the server which simply sends the contents of the buffer without including messagesize back to the client, I'd say it was a fair assumption at the time.

What Hunter2 said about your messages possibly being fragmented is just one of the many things you have to consider in writing a production quality server.

09-30-2004

Hunter2

>>That's easy to point out when you have the benefit of seeing all the relevant code I did not.
Don't see what you mean... the code was in the first post he made.

>>Without seeing the client-side code, it was not possible to know he'd included the messagesize in his packet.
If you don't know the protocol, don't assume that the messagesize isn't sent... because it almost always is. And you can see later that he uses messagesize in recv() to determine the number of bytes to receive.

Quote:

Looking at the code on the server which simply sends the contents of the buffer without including messagesize back to the client, I'd say it was a fair assumption at the time.

Since I'm finding the code very difficult to read and therefore have no intention of reading it, I won't argue with you there :)

09-30-2004

codec

I'd agree with you on the readability of the code, it's not the best. From what I can tell it seems to be a mix of copy+paste from different tutorials and therefore coding styles without much re-formatting.

>> Don't see what you mean... the code was in the first post he made.
I meant that he didn't include the client side code or any sort of rough protocol spec. meaning it was impossible to know what data was being processed. This caused me to go on the only code which constructs a packet in his first post which doesn't include a message size. Looks like it was a bad assumption, but we should get on with helping our friend here :) Thanks for correcting my error.

How's things going m1lk? Let us know -exactly- what you're after and what problems you're having and I'm more than willing to help, it's a tough subject. If you don't understand any of the tips anyone's given, you can always ask for it to be explained in more detail.

09-30-2004

codec

Also, check out this post I made if you're looking to incorporate your send()s into your select() statement at some point.