Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


UDP Question...


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
13 replies to this topic

#1 Miraj   Members   -  Reputation: 122

Like
Likes
Like

Posted 14 March 2000 - 06:48 PM

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

Sponsor:

#2 SiCrane   Moderators   -  Reputation: 9625

Like
Likes
Like

Posted 14 March 2000 - 07:27 PM

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.

#3 Miraj   Members   -  Reputation: 122

Like
Likes
Like

Posted 14 March 2000 - 08:24 PM

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


#4 SiCrane   Moderators   -  Reputation: 9625

Like
Likes
Like

Posted 14 March 2000 - 08:30 PM

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.

#5 Miraj   Members   -  Reputation: 122

Like
Likes
Like

Posted 15 March 2000 - 01:06 AM

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...

#6 Jeff K   Members   -  Reputation: 122

Like
Likes
Like

Posted 15 March 2000 - 03:02 AM

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));

#7 Miraj   Members   -  Reputation: 122

Like
Likes
Like

Posted 15 March 2000 - 06:04 PM

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


#8 SiCrane   Moderators   -  Reputation: 9625

Like
Likes
Like

Posted 15 March 2000 - 06:16 PM

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.

#9 Miraj   Members   -  Reputation: 122

Like
Likes
Like

Posted 16 March 2000 - 01:46 AM

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


#10 Jeff K   Members   -  Reputation: 122

Like
Likes
Like

Posted 16 March 2000 - 03:05 AM


#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

#11 Miraj   Members   -  Reputation: 122

Like
Likes
Like

Posted 18 March 2000 - 01:45 AM

Well, one tumor and three days later I think (I THINK) the pieces of the puzzle are finally fitting

Thanks guys for helping out. I seriously couldn''t have done this without the help/snippets. I learned a hell of alot about Winsock, thats for sure.

I wanted to refrain from bothering anyone anymore about this but I do have this one minor glitch that is happening

Is there any possible reason why the client would freeze after recieving a packet? ;( I''ve checked *everything* over and over, numerous times and I just can''t see what would cause it to do that. I have all the nessecary code in order to process the information and don''t get it at all...

-Miraj


#12 daveb   Members   -  Reputation: 122

Like
Likes
Like

Posted 21 March 2000 - 10:27 AM

You might try making sure the socket you're reading-from/writing-to is operating in non-blocking mode. A blocking select or recvfrom() call could be causing this.

Edited by - daveb on 3/21/00 4:29:06 PM

#13 kressilac   Members   -  Reputation: 110

Like
Likes
Like

Posted 22 March 2000 - 03:23 AM

Miraj,

While reading this post, I noticed something that you are doing that needs to be addressed. In your linked list implementation you were calling send(... IPEntries...) and in your array implementation you called IPList. I think you need to look into iterating and traversing lists of data structures. Both of these issues in your code were related to traversing the list. Jeff fixed it in his. Take note of how he used a for loop to iterate the array list using the index instead of just passing the pointer to the array thinking it will iterate itself.

To iterate an array use his code.

for (int counter = 0; counter == MAX_COUNTER; counter++) {
Do something using the array[counter].
}

To iterate a linked list use the following if you are sure you will always ready every node.

for (Node *pnode = ListHead; !pnode; pnode = pnode->next) {
Do something for pnode->value.
}

Use a while loop instead of a for loop if you think you will stop iterating midway through the linked list. I hope this helps and sorry to get a listtle off topic there, but figured it needed to be mentioned.

Kressilac

Edited by - kressilac on 3/22/00 9:26:14 AM

#14 Miraj   Members   -  Reputation: 122

Like
Likes
Like

Posted 23 March 2000 - 02:51 AM

Daveb, Kressilac,

Thanks for the input guys. I finally got everything working thanks to all the great responses.

Daveb: You were right about the blocking, that was the problem. I set the appropriate flag and it stopped. I don''t know how I overlooked that.

Kressilac: Thanks for pointing that out. I''m really not that experienced with linked lists yet. It seemed like a reasonable solution to what I wanted to do but I was definatly weak on the implementation of it.

Thanks again!






-Miraj





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS