This may well be considered a frequently asked questions about UDP networking, because I think I have to ask just about every question under the sun about it. I'm trying to understand how to do the most basic things with UDP but I'm not quite getting it. It's partly because not much of it is clearly documented and partly because this just isn't seemingly discussed much. I'm sorry about the sheer length of this and the number of questions, but this is stuff that I and others really need to know.
I've tried looking at some networking libraries but for the most part that isn't entirely helping. I know that UDP is a bare-bones protocol with no `connections` that just send out packets hoping they will arrive while the other end waits to receive something from some unknown sender.
I want to put together or use really basic commands to just open a port for sending, open a port for receiving, then send or receive packets of byte data ie like between a server and a client, or two peers. Nothing fancy at this point, I can expand with features later. I don't want to turn to a third party network library, I want to understand how to do this myself.
From what I gather, either you need to use really low-level commands which are not documented and refer to C include files, like `send_`, `recv_` etc, or use TSocket which wraps them fairly lightly into more user-friendly methods such as Send() and Receive(). So this is largely going to be questions about using TSocket.
So I have some questions and I'm sure many other people want to know about this too.
1. How the h*** do you actually set up a port on each machine ready for sending/receiving data? What commands are needed and what is the format and what data do you have to pass to it? From looking at the code for the TSocket type, my guess is that you need to do something like:
Is this code even right?
2. What port number should you pass to Bind()? I read online about reserved ports and all that, seems like you have to use numbers from 50000 to 64000 or so, but I see other people using ports like 80 or 8080 or whatever? How do you choose a port number and why do you choose it?
3. Does the port number you choose to be bound to on the client machine have to match with the port number of the server machine or can they be different so long as they both know which port to send TO? e.g If the client sends and receives on port 50000 and the server on port 55000, it will work so long as the server receives on 55000 and sends to 50000, and vice versa?
Is there any reason to make them the same port number on both?
4. If trying to bind the port fails, should you just try another port number? How many should you try? How should you space them out? Are there safe or likely-to-work numbers you should use? How do you know which ones are available?
5. Is the RemoteIPNumber just an integer representation of the dotted IP? Ie something like 156.341.192.39 could be the address of the server machine that you want to connect to, so you need to convert this to an integer representation to use with the Connect() method? The question of where to get the server's IP address from is not important right now but I would like to know how to convert such an address into the appropriate value to use with Connect() ??? DottedIP() seems to convert from an IP integer to a dotted version but how do you convert the other way? Do you use HostIP() and if so what data do you pass to it? Like HostIP("156.341.192.39",0) ???
6. Do I actually need to call Connect() at all for use with UDP? e.g. to set the remote address and port that I'm sending to? I presume in order for the client machine to build a UDP datagram packet it has to know what destination IP and port number to send it to, to put into the packet header, so somewhere that has to be set, right? So does Connect() just set that information, but not actually try to send anything like TCP would? I know for a TCP connection it has to do a handshake but UDP does not. So do I just do Connect(RemoteIP,RemotePort) and it immediately returns, having just set that data ready for future sending and having not actually sent anything?
7. Is there anything else I need to do to set up the client for this readiness to send out UDP packets?
Assuming we've got this far and the port and addresses and all that are set up correctly and is just waiting to send stuff...
8. Do I just call Sock.Send(MyMemoryBufferBytePtr,NumberOfBytes,Flags)?
9. When I do call Sock.Send(), what are the possible values for the Flags and why might I use them?
10. Each time I call Sock.Send() will it actually send out the UDP packet right away or does it add it to some kind of accumulative buffer until a certain number of bytes are in the packet, or would I need to write that as a separate abstraction layer myself?
11. How many bytes should I send with each call to Send()? I have heard different numbers like no more than 1500, no more than 1200, no less than 64 due to it automatically padding it to at least 64 bytes, etc. Is there a way to detect what the maximum number of bytes is that would work without it flooding? Does it depend on the client's transmission hardware and/or the server's hardware? What size do you recommend that is widely supported, 1024 bytes? Do I need to play it safe or is there a way to actually determine the size?
12. Is there anything else I need to do to cause the system to send out the packet I've given to the Send() method?
Presuming this is all there is to it, we then move on to assuming that the packet was sent to the address provided in Connect() at the port provided, and that the packet actually does make it to that address and port (I know this is unlikely sometimes, but for the sake of proceeding)...
13. What is the server now doing to look for or anticipate this potentially incoming packet, having absolutely no prior knowledge of the computer it is being sent from or what is being sent in the packet? I presume at the very least the server will have set up a similar process whereby it says someting like:
Is this correct?
14. Presumably you cannot use Connect() because you don't know who is going to be sending a packet to the server or where from, right, or is this a requirement at this point? Do I need to know the IP and port of the computer that is going to be sending packets to me, prior to them having ever sent any at all? Or is there a way to just listen for `any packet` that might be available? And if so, how?
15. I presume this is where I would use the Sock.Recv() method on the server, in some kind of loop which occasionally tries to receive data from the socket. From looking at the code in the Socket type it looks like it tries to read data from the socket into a byte buffer at some address and then tells you how many bytes it read, or what looks to be 0 if there were none (am I on the right track?). It also looks like you can tell it how many bytes to receive at a time, so that you don't overwhelm your own buffer space. So if I'm understanding this, does the server now just sit in a loop and call Sock.Recv(MyStorageBufferBytePtr,MyStorageBufferSize,Flags), keeping track of the value that is returned until that value >0? And when it is >0 does this mean that I've successfully received *something* from *someone* with a given number of bytes, up to the size of my storage space?
16. Does Recv() allow packet data to come in regardless of who sent it or from which port? Or is there something I have to do in order to allow it to receive data from a given sender? I noticed that for TCP there is Accept() and also ReadAvail(), but do these apply to UDP at all? I guess I can use ReadAvail() to tell me if bytes have arrived without actually transferring them to my buffer, for UDP as well as TCP? Do I need to do an Accept() for UDP? and does ReadAvail() tell you that bytes arrived even if you still don't know yet who sent them or from where?
17. Assuming that I would now be at the point where data is beginning to come in from somewhere, and assuming that I didn't need to do anything else to allow that data to arrive from a given client, does the data that gets transferred to my memory space include the UDP header information or is it purely the payload that the client gave to the Send() method, and only the amount of bytes that it gave?
18. If I get say 200 bytes of data from client A and 200 bytes from client B at the same time, presuming client A's data went into the buffer first followed by B's, so I then need to read my memory buffer in such a way that I know where client A's data ends and client B's data begins? Like, by sending a `length` value or using some kind of delimiter? ie does my input `stream` of byte data end up being just all the packet payloads concatenated after each other and I have to divide it up myself into actual `packets`?
19. Once I have some data received into my buffer and I've determined the size of the packet - and maybe it fits into my buffer or is the result of several calls to Recv() joined together, how do I determine what IP address and port it came from? From what I gather this information is in the UDP packet and I know some libraries like BNetEx are able to `sniff` the packet header to find out who sent it, is there a way that I have access to this data using only the TSocket methods/functions, or is that something you'd have to do at a lower level working with the o/s calls? Is that simple to do, while also using TSocket? And what is the alternative - just have the client send their IP address and Port number as a part of the byte data payload, ie as two integers?
20. Do I ever need to use the Listen() method with UDP? Seems to me listening sounds like waiting. Does it apply to UDP?
21. If I use Sock.Close() does that close the entire socket and all ports it is associated with? If so, can I then reopen another socket and bind it to the same ports? Can you have more than one socket bound to the same port at the same time?
22. Does the Sock.Connected() method work with UDP, since it does not really have connections?
23. How do I find out what the IP address is of the client's machine, presuming they don't know how to go looking for it manually? I will need to send this IP address to the server so what are the appropriate methods or functions to call to get this IP address either as an integer or as a dotted/human-readable version? I presume DottedIP$() returns the dotted version of the IP integer, but how do I get either from the client's machine in a reliable way that will definitely work? I've seen a few approaches here and there so I am confused which one works.
24. What is the 127.0.0.1 or whatever it is? What is it for? Why would you use it? How does it work?
25. Can I use RemoteIP() or RemotePort() to get the IP and port of the client after they send a packet to the server, or does this purely tell me what I already know - which IP and port I already said I was sending data TO?
26. Can multiple users access the same port on the server? Should I give each user their own port to avoid flooding the entire system? If so, can I just add 1 to each port number each time (within the allowed range?) I read that maybe you should receive `connection attempts` on one specific port and then give each user their own port?
27. Do I need to open multiple sockets for any reason whatsoever? ie if I want multiple ports, do I need one socket for each port or can a socket have multiple ports? (The code looks like it has one port per socket?)
28. If I close a socket on the server with Close(), will that mean that if the client still sends packets to that port at the server it just will be ignored by the TCP stack or whatever? And if they get absolutely no response from the server (e.g. downtime) would I have to code it into the client to interpret this to mean `server is not available`?
29. What does the UpdateLocalName() method do? It appears to be related to the IP address of the computer that the application is running on? Why would this likely change and why might I want to call this method directly?
30. Same applies to UpdateRemoteName(), what does it do and why would I use it?
31. Presuming that at this point I have set up the client and the server (or peers) with open ports ready to receive data and am receiving it correctly and sending stuff back and forth, is there anything else important that I need to know - any do's or don'ts?
I know that on top of these basics you could have a whole host of features like authentication, different topology models, streaming, dynamic bandwidth adjustment, logging-in/logging-out, sending files/chats, putting together game packets, etc. That stuff actually seems easier to understand and implement to me. It's this fundamental UDP stuff that I am not quite grasping. Any help is greatly appreciated.
I've tried looking at some networking libraries but for the most part that isn't entirely helping. I know that UDP is a bare-bones protocol with no `connections` that just send out packets hoping they will arrive while the other end waits to receive something from some unknown sender.
I want to put together or use really basic commands to just open a port for sending, open a port for receiving, then send or receive packets of byte data ie like between a server and a client, or two peers. Nothing fancy at this point, I can expand with features later. I don't want to turn to a third party network library, I want to understand how to do this myself.
From what I gather, either you need to use really low-level commands which are not documented and refer to C include files, like `send_`, `recv_` etc, or use TSocket which wraps them fairly lightly into more user-friendly methods such as Send() and Receive(). So this is largely going to be questions about using TSocket.
So I have some questions and I'm sure many other people want to know about this too.
1. How the h*** do you actually set up a port on each machine ready for sending/receiving data? What commands are needed and what is the format and what data do you have to pass to it? From looking at the code for the TSocket type, my guess is that you need to do something like:
'Client trying to connect to someone Local Sock:TSocket=Sock.CreateUDP() If Sock=Null then CantCreateUDPSocket() 'deal with failure Local Success:Int=Sock.Bind(MyPortNumber) 'what port? If Success=False Then CantBindThePort() 'deal with failure Sock.Connect(RemoteIPNumber,RemotePortNumber)
Is this code even right?
2. What port number should you pass to Bind()? I read online about reserved ports and all that, seems like you have to use numbers from 50000 to 64000 or so, but I see other people using ports like 80 or 8080 or whatever? How do you choose a port number and why do you choose it?
3. Does the port number you choose to be bound to on the client machine have to match with the port number of the server machine or can they be different so long as they both know which port to send TO? e.g If the client sends and receives on port 50000 and the server on port 55000, it will work so long as the server receives on 55000 and sends to 50000, and vice versa?
Is there any reason to make them the same port number on both?
4. If trying to bind the port fails, should you just try another port number? How many should you try? How should you space them out? Are there safe or likely-to-work numbers you should use? How do you know which ones are available?
5. Is the RemoteIPNumber just an integer representation of the dotted IP? Ie something like 156.341.192.39 could be the address of the server machine that you want to connect to, so you need to convert this to an integer representation to use with the Connect() method? The question of where to get the server's IP address from is not important right now but I would like to know how to convert such an address into the appropriate value to use with Connect() ??? DottedIP() seems to convert from an IP integer to a dotted version but how do you convert the other way? Do you use HostIP() and if so what data do you pass to it? Like HostIP("156.341.192.39",0) ???
6. Do I actually need to call Connect() at all for use with UDP? e.g. to set the remote address and port that I'm sending to? I presume in order for the client machine to build a UDP datagram packet it has to know what destination IP and port number to send it to, to put into the packet header, so somewhere that has to be set, right? So does Connect() just set that information, but not actually try to send anything like TCP would? I know for a TCP connection it has to do a handshake but UDP does not. So do I just do Connect(RemoteIP,RemotePort) and it immediately returns, having just set that data ready for future sending and having not actually sent anything?
7. Is there anything else I need to do to set up the client for this readiness to send out UDP packets?
Assuming we've got this far and the port and addresses and all that are set up correctly and is just waiting to send stuff...
8. Do I just call Sock.Send(MyMemoryBufferBytePtr,NumberOfBytes,Flags)?
9. When I do call Sock.Send(), what are the possible values for the Flags and why might I use them?
10. Each time I call Sock.Send() will it actually send out the UDP packet right away or does it add it to some kind of accumulative buffer until a certain number of bytes are in the packet, or would I need to write that as a separate abstraction layer myself?
11. How many bytes should I send with each call to Send()? I have heard different numbers like no more than 1500, no more than 1200, no less than 64 due to it automatically padding it to at least 64 bytes, etc. Is there a way to detect what the maximum number of bytes is that would work without it flooding? Does it depend on the client's transmission hardware and/or the server's hardware? What size do you recommend that is widely supported, 1024 bytes? Do I need to play it safe or is there a way to actually determine the size?
12. Is there anything else I need to do to cause the system to send out the packet I've given to the Send() method?
Presuming this is all there is to it, we then move on to assuming that the packet was sent to the address provided in Connect() at the port provided, and that the packet actually does make it to that address and port (I know this is unlikely sometimes, but for the sake of proceeding)...
13. What is the server now doing to look for or anticipate this potentially incoming packet, having absolutely no prior knowledge of the computer it is being sent from or what is being sent in the packet? I presume at the very least the server will have set up a similar process whereby it says someting like:
'Server getting ready to receive client data Local Sock:TSocket=Sock.CreateUDP() If Sock=Null then CantCreateUDPSocket() 'deal with failure Local Success:Int=Sock.Bind(MyPortNumber) 'what port? If Success=False Then CantBindThePort() 'deal with failure
Is this correct?
14. Presumably you cannot use Connect() because you don't know who is going to be sending a packet to the server or where from, right, or is this a requirement at this point? Do I need to know the IP and port of the computer that is going to be sending packets to me, prior to them having ever sent any at all? Or is there a way to just listen for `any packet` that might be available? And if so, how?
15. I presume this is where I would use the Sock.Recv() method on the server, in some kind of loop which occasionally tries to receive data from the socket. From looking at the code in the Socket type it looks like it tries to read data from the socket into a byte buffer at some address and then tells you how many bytes it read, or what looks to be 0 if there were none (am I on the right track?). It also looks like you can tell it how many bytes to receive at a time, so that you don't overwhelm your own buffer space. So if I'm understanding this, does the server now just sit in a loop and call Sock.Recv(MyStorageBufferBytePtr,MyStorageBufferSize,Flags), keeping track of the value that is returned until that value >0? And when it is >0 does this mean that I've successfully received *something* from *someone* with a given number of bytes, up to the size of my storage space?
16. Does Recv() allow packet data to come in regardless of who sent it or from which port? Or is there something I have to do in order to allow it to receive data from a given sender? I noticed that for TCP there is Accept() and also ReadAvail(), but do these apply to UDP at all? I guess I can use ReadAvail() to tell me if bytes have arrived without actually transferring them to my buffer, for UDP as well as TCP? Do I need to do an Accept() for UDP? and does ReadAvail() tell you that bytes arrived even if you still don't know yet who sent them or from where?
17. Assuming that I would now be at the point where data is beginning to come in from somewhere, and assuming that I didn't need to do anything else to allow that data to arrive from a given client, does the data that gets transferred to my memory space include the UDP header information or is it purely the payload that the client gave to the Send() method, and only the amount of bytes that it gave?
18. If I get say 200 bytes of data from client A and 200 bytes from client B at the same time, presuming client A's data went into the buffer first followed by B's, so I then need to read my memory buffer in such a way that I know where client A's data ends and client B's data begins? Like, by sending a `length` value or using some kind of delimiter? ie does my input `stream` of byte data end up being just all the packet payloads concatenated after each other and I have to divide it up myself into actual `packets`?
19. Once I have some data received into my buffer and I've determined the size of the packet - and maybe it fits into my buffer or is the result of several calls to Recv() joined together, how do I determine what IP address and port it came from? From what I gather this information is in the UDP packet and I know some libraries like BNetEx are able to `sniff` the packet header to find out who sent it, is there a way that I have access to this data using only the TSocket methods/functions, or is that something you'd have to do at a lower level working with the o/s calls? Is that simple to do, while also using TSocket? And what is the alternative - just have the client send their IP address and Port number as a part of the byte data payload, ie as two integers?
20. Do I ever need to use the Listen() method with UDP? Seems to me listening sounds like waiting. Does it apply to UDP?
21. If I use Sock.Close() does that close the entire socket and all ports it is associated with? If so, can I then reopen another socket and bind it to the same ports? Can you have more than one socket bound to the same port at the same time?
22. Does the Sock.Connected() method work with UDP, since it does not really have connections?
23. How do I find out what the IP address is of the client's machine, presuming they don't know how to go looking for it manually? I will need to send this IP address to the server so what are the appropriate methods or functions to call to get this IP address either as an integer or as a dotted/human-readable version? I presume DottedIP$() returns the dotted version of the IP integer, but how do I get either from the client's machine in a reliable way that will definitely work? I've seen a few approaches here and there so I am confused which one works.
24. What is the 127.0.0.1 or whatever it is? What is it for? Why would you use it? How does it work?
25. Can I use RemoteIP() or RemotePort() to get the IP and port of the client after they send a packet to the server, or does this purely tell me what I already know - which IP and port I already said I was sending data TO?
26. Can multiple users access the same port on the server? Should I give each user their own port to avoid flooding the entire system? If so, can I just add 1 to each port number each time (within the allowed range?) I read that maybe you should receive `connection attempts` on one specific port and then give each user their own port?
27. Do I need to open multiple sockets for any reason whatsoever? ie if I want multiple ports, do I need one socket for each port or can a socket have multiple ports? (The code looks like it has one port per socket?)
28. If I close a socket on the server with Close(), will that mean that if the client still sends packets to that port at the server it just will be ignored by the TCP stack or whatever? And if they get absolutely no response from the server (e.g. downtime) would I have to code it into the client to interpret this to mean `server is not available`?
29. What does the UpdateLocalName() method do? It appears to be related to the IP address of the computer that the application is running on? Why would this likely change and why might I want to call this method directly?
30. Same applies to UpdateRemoteName(), what does it do and why would I use it?
31. Presuming that at this point I have set up the client and the server (or peers) with open ports ready to receive data and am receiving it correctly and sending stuff back and forth, is there anything else important that I need to know - any do's or don'ts?
I know that on top of these basics you could have a whole host of features like authentication, different topology models, streaming, dynamic bandwidth adjustment, logging-in/logging-out, sending files/chats, putting together game packets, etc. That stuff actually seems easier to understand and implement to me. It's this fundamental UDP stuff that I am not quite grasping. Any help is greatly appreciated.