Confused about UDP sockets in C #

I was just starting to learn sockets through various Google searches, but I was having trouble figuring out how to use Sockets correctly in C # and I need some help.

I have a test application (Windows Forms) and on another class (which is actually located in it .dll, but it does not matter) I have all the server / client code for my socket code.

Question 1)

In my test application, on the server part, the user can click the “start listening” button, and the server part of the socket application should start listening on the connections at the specified address and port, as far as it is good.

However, the application will be blocked, and I can not do anything until someone connects to the server. What if no one connects? How can I handle this? I can indicate the waiting time for the reception, but then what? Does that rule out what I can do about it? I would like to have some activity in the main application, so that the user knows that the application has not frozen and is waiting for connections. But if the connection does not occur, it should be delayed and close everything.

Perhaps I should use asynchronous calls to the send and receive methods, but they seem confusing, and I could not get it to work, only synchronous work (I will lay out my current code below).

Question 2)

Do I need to close something when the time for sending and receiving calls expires. As you will see in my current code, I have a bunch of closures in the socket, but this is somehow not the case. But it also doesn’t feel good when the time works, and I do not close the socket.

In conclusion of my two questions .... I would like the application not to be blocked, so that the user knows that the server is waiting for a connection (for example, with a small tent animation). If the connection is not established after some time, I want to close everything that should be closed. When the connection is established or if this does not happen after some time, I would like to inform the main application of the result.

Here are some of my code, the rest is similar. The Packet class is a custom class that is a custom data block, it's just a bunch of properties based on enums , now with methods for converting them into bytes and back into properties.

A function that starts listening for connections looks something like this:

 public void StartListening(string address, int port) { try { byte[] bufferBytes = new byte[32]; if(address.Equals("0.0.0.0")) { udpSocket.Bind(new IPEndPoint(IPAddress.Any, port)); } else { udpSocket.Bind(new IPEndPoint(IPAddress.Parse(address), port)); } remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); int numBytesReceived = udpSocket.ReceiveFrom(bufferBytes, ref remoteEndPoint); if(numBytesReceived == 0) { udpSocket.Close(); return; } Packet syncPacket = new Packet(bufferBytes); if(syncPacket.PacketType != PacketType.Control) { udpSocket.Close(); return; } } catch { if(udpSocket != null) { udpSocket.Close(); } } } 

I am sure that I have a bunch of unnecessary code, but I'm new to this, and I'm not sure what to do, any help correcting my code and solving the above problems is really appreciated.

EDIT:

I probably should have said that my requirements were to use UDP and implement these things on my own at the application level. You can consider this as homework, but I am not marked as such because the code does not matter and will not be part of my class, and my problem (my question) is in “how to encode”, since my socket experience is minimal and this not taught.

However, I have to say that I solved my problem at the moment, I think ... I used streams in a demo application that gave me some problems, now I use it in protocol connections, it makes more sense, and I can easily change my own properties of the protocol class and read them from the demo application.

I set a timeout and threw a SocketException if it reaches a timeout. Whenever such an exception occurs, the socket connection is closed. I'm just talking about making a connection, nothing more. If no exceptions are found, the code is likely to be smooth and the connection will be established.

Please adapt your answers accordingly. Right now, it makes no sense for me to mark any of them as an accepted answer, I hope you understand.

+6
c # udp networking sockets
source share
2 answers

You have a little bad business.

First of all, UDP has no connection. You are not connecting or disconnecting. All you do is send and receive (each time specify the addressee). You should also know that the only UDP promises is that a complete message arrives for every read. UDP does not guarantee that your messages arrive in the correct order or that they arrive at everything.

TCP, on the other hand, is connection-based. You connect, send / receive, and finally disconnect. TCP is stream-based (while UDP is message-based), which means you can receive half the message in the first reading and the other in the second reading. TCP promises you that everything will arrive and in the correct order (or die trying;). Therefore, using TCP means that you must have some kind of logic to know when the full message arrived, and the buffer you use to create the full message.

The next big question was about blocking. Since you're new to this, I recommend using Threads to handle sockets. Place the listener socket on one thread and each connector socket on a separate thread (5 connected clients = 5 threads).

I also recommend that you use TCP because it is easier to create complete messages than to order messages and create a transaction system (which is necessary if you want all messages to come to / from clients).

Update

You still have UDP. Close does nothing but clean up system resources. Instead, you should do something like this:

 public void MySimpleServer(string address, int port) { try { byte[] bufferBytes = new byte[32]; if(address.Equals("0.0.0.0")) { udpSocket.Bind(new IPEndPoint(IPAddress.Any, port)); } else { udpSocket.Bind(new IPEndPoint(IPAddress.Parse(address), port)); } remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); while (serverCanRun) { int numBytesReceived = udpSocket.ReceiveFrom(bufferBytes, ref remoteEndPoint); // just means that one of the clients closed the connection using Shutdown. // doesnt mean that we cant continue to receive. if(numBytesReceived == 0) continue; // same here, loop to receive from another client. Packet syncPacket = new Packet(bufferBytes); if (syncPacket.PacketType != PacketType.Control) continue; HandlePacket(packet, endPoint); } } catch { if(udpSocket != null) { udpSocket.Close(); } } } 

Cm? since there is no connection, it is just a waste of time to close the UDP socket to start listening from another. The same socket can receive from all udp clients who know the correct port and address. What is remoteEndPoint ? It tells which client is sending the message.

Update 2

A small update to compile a summary of all my comments.

UDP connectionless. You will never be able to determine if a connection is established or disconnected. The Close method in UDP juice will free up system resources only. Calling client.Close() will not notify the server socket (as it will be with TCP).

The best way to check if a connection is open is to create a ping / pong package style. that is, the client sends a PING message, and the server responds with a PONG. Remember that UDP will not try to resend your messages if they do not arrive. Therefore, you need to resend PING a couple of times before assuming the server is down (unless you received PONG).

As for closing clients, you need to send your own message to the server, telling him that the client will stop talking to the server. For reliability, the same thing happens here, continue to resend the BYE message until you get a response.

imho is imperative that you implement a transactional system for UDP if you want reliability. SIP (google rfc3261) is an example of a protocol that uses transactions over UDP.

+9
source share

From your description, I believe that you should use TCP sockets instead of UDP. The difference is

TCP You are waiting for a connection on the IP side: the port to which the user can connect, and until the socket is closed, it can communicate by sending and receiving information. It’s like calling someone on the phone.

UDP - you are waiting for a message on some IP: port. A user who wants to communicate simply sends a message via UDP. You will receive a message through UDP. Delivery order is not guaranteed. This is more like sending someone snail mail. The established communication channel is not installed.

Now let's get to your problem

Server

  • Create a socket with the TCP family.
  • Either create a stream and accept the connection in that stream, or use Apis BeginAccept for Socket.
  • In the main thread, you can display a ticker or whatever you want to do.

Client

  • Connect to the server.
  • Communicate by sending and receiving data.
0
source share

All Articles