🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

UDP Question...

Started by
12 comments, last by Miraj 24 years, 3 months ago
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
-Miraj
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.
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
-Miraj
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.
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...
-Miraj
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));
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
-Miraj
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.
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
-Miraj
#define MAX_IP 1000struct 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

This topic is closed to new replies.

Advertisement