• Advertisement

Archived

This topic is now archived and is closed to further replies.

UDP Question...

This topic is 6605 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Does anyone have any sample source code of getting data from a client, then echoing it out to all clients? Or any tutorials that might cover the topic? I can have the server echo the data back to the one client that originally sent it but I don''t know how to update them all. I''m using UDP. Any help would be great, thanks. -Miraj

Share this post


Link to post
Share on other sites
Advertisement
I''m assuming you''re using winsock.

Ok, currently, once you''ve recvfrom()''d from one socket, you sendto() out that same buffer you just received. So instead sento() to all the current client. Just keep a list of all your clients and their sockaddr data structures, and you should have no problem.

I do have to say, that the system you seem to want to set up would work better in a connection oriented protocol.

Share this post


Link to post
Share on other sites
Hi,

I am using Winsock. I understand what your saying. So what if i did this. Upon the client logging into the server, it would hand over its hostname or IP, the server would then add it to its table of addresses, then when the time comes to update everyone do a sendto() to all the IP''s in the table. Am I on the right track or am i forgetting something? And if so, what would you say the best method is for keeping track off all the hostnames, an array maybe?



-Miraj

Share this post


Link to post
Share on other sites
Well, you don''t need the client to explicitly handover it''s hostname. All you need to do is check to see if the packet is a "login" packet. The recvfrom() call should fill a sockaddr structure. You can get the IP from that struct. Probably an array would be easiest. IP addresses occupy only a long int, so storing up a thousand would only take up 4K memory. If you''re a fan of STL (I''m not) probably the best structure would be a vector.

Share this post


Link to post
Share on other sites
Okay, I think I''m getting this.

So if I wanted to get the IP from the sockaddr structure what would I use, gethostbyaddr()?

I''ve tried a few variations, just messing around and I can''t really get it to work. Before getting into anything like actually storing all the addresses I just tried to printf the address, something like:

printf("Address is:", &data);

I tried getting some information on MSDN and there isn''t much there. Maybe I''m just missing something...

Share this post


Link to post
Share on other sites
struct sockaddr_in addr;
int len, addr_len;
char buf[8192];

addr_len = sizeof(addr);
len = recvfrom(sock, buf, sizeof(buf), (struct sockaddr*)&addr, &addr_len);

if (len > 0)
printf("received %d bytes from %s:%d\n", len,
inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

Share this post


Link to post
Share on other sites
Okay, I''ve got that much working. Thanks Jeff, I was missing the "inet_ntoa(addr.sin_addr), nto (addr.sin_port));" part

What I decided to do was create a linked list and use that to hold all of the IP''s. But it is not working. Here is the code, its not all of it, just the relevant part of the data handling.

-----------------------------------------------------------
struct sockaddr_in addr; // Address
char buffer[PACKET_SIZE]; // Maximum size of packets
int Read;
int Sent;
int len = sizeof (SOCKADDR); // Number of bytes...
struct sockaddr_in NewIP; // Hold any new addresses...

struct IPEntries // Client database structure...
{
struct sockaddr_in IP; // IP number
struct IPEntries *next;
} start, *node;

start.next = NULL; // Empty List...
node = &start; // Point to beginning of list...

// Handle data...
memset (buffer, ''\0'', PACKET_SIZE);
// Listen for packets...
Read = recvfrom (ServerSocket, buffer, PACKET_SIZE, 0, (struct sockaddr*)&addr , &len);

// If no packets begin again...
if (Read == -1)
return;

node->next = (struct IPEntries *) malloc(sizeof(struct IPEntries));
NewIP = addr; // Put our new address in NewIP.
node = node->next;
node->IP = NewIP; // Add it to the list...
node->next = NULL; //....

printf ("Packet : \"%s\", %d bytes, ", buffer,Read);
printf ("echoed %d bytes back\n", Sent);
printf("received %d bytes from %s:%d\n", len, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

// update clients...
Sent = sendto(ServerSocket, buffer, strlen(buffer), 0, (SOCKADDR *)&IPEntries, sizeof (SOCKADDR));

Now I know this is all wrong but am I at least on the right track? If you can find any exact problems here and offer any solutions that''d be great.

Thanks...


-Miraj

Share this post


Link to post
Share on other sites
I''m pretty sure you can''t simply do assignment on your sockaddr_in structs. You''ll probably need to memcpy the contents.
Also your sendto() is being called on IPEntries... which is a struct definition. Did that even compile?
You''ll need iterate through your needs and call the sendto() on the acutal pointer to the sockaddr_in struct in each node.

Share this post


Link to post
Share on other sites
Oh it compiled, with about 30 warnings

Okay, after thinking about arrays I had a moment of weakness
and thought I would go the route of Linked lists. Much too complicated (for me anyway ).

So I''ve gone back to the original idea, of arrays. I''ve memcpy''d the address like you suggested and it is much better.

So doing away with the LLists, I now have memcpy which copies &addr, into &IPList. IPList has looks like this...

IPList[1000];

then i sendto &IPList, and it works, in a sense, because it is echoed back to the original sender, but still not to to both. (I''m testing this with 3 computers, you have no idea how annoying it is to have to get up every 2 minutes after changing the code and testing all three again, on and on, all night ... doh).

After some thinking, I realized one of the reasons (and something that could cause problems down the line) is that the server will only know the client exists once it has recieved at least one login packet and been added to the list. I think that is what you were talking about earlier as well, so I had them each send a login packet first, and tried and still nothing.

So I guess what I need to do is figure out a way to add a new address to the array, but somehow make sure the next new address doesn''t overwrite the previous one in the first byte of IPEntries. Then repeating that and so on, up to 1000, or whatever. Once I have that going, It should work flawlessly i think. But how?





-Miraj

Share this post


Link to post
Share on other sites

#define MAX_IP 1000
struct sockaddr_in iplist[MAX_IP];
int ipcount = 0;

int ipequal(struct sockaddr_in *a, struct sockaddr_in *b)
{
if (a->sin_addr.s_addr != b->sin_addr.s_addr) return 0;
if (a->sin_port != b->sin_port) return 0;
return 1;
}
void add_ip(struct sockaddr_in *addr)
{
int i;
if (ipcount >= MAX_IP) return;
for (i = 0; i < ipcount; i++) {
/* avoid adding duplicates */
if (ipequal(addr, &iplist[i])) return;
}
iplist[ipcount] = *addr;
ipcount++;
}
void server_loop(int server_socket)
{
char buf[8192];
struct sockaddr_in addr;
int i, len, addr_len;

while (1) {
addr_len = sizeof(addr);
len = recvfrom(server_socket, buf, sizeof(buf), 0, (struct sockaddr *)&addr, &addr_len);
if (len < 0) break;
printf("received %d bytes from %s:%d\n", len, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
add_ip(&addr);
for (i = 0; i < ipcount; i++) {
if (ipequal(&addr, &iplist[i])) continue;
sendto(server_socket, buf, len, 0, (struct sockaddr *)&iplist[i], sizeof(iplist[i]));
}
}
}

After about a dozen edits I finally get this formatting code right...

Edited by - Jeff K on 3/16/00 9:28:48 AM

Share this post


Link to post
Share on other sites

  • Advertisement