🎉 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!

An existing connection was forcibly closed by the remote host - UDP Issue

Started by
16 comments, last by hplus0603 5 years, 5 months ago

I'm attempting to setup UDP for a multiplayer game I'm developing but I've been having lots of issue trying to get the UDP packets to send over to my clients as it seems my UDP listener (UDPClient) isn't setup correctly but I have no idea why. This is for an assignment and they didn't give us much help on it so I'm a little clueless to be honest which is likely why it isn't working. I'll go over what I've got currently.

Currently I've got it setup where my clients will have their own UDPSocket and UdpEndPoint(IPEndPoint). I initialize the Socket when creating the Client object, and then create the endpoint and connect the socket to it when the user connects to the server. The IP and Port numbers are 127.0.0.1 and 4444 respectively 


public Client()
    {
        tcpClient = new TcpClient();
        formatter = new BinaryFormatter();

        udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    }

    public bool Connect(string ipAddress, int port)
    {
        try
        {
            tcpClient.Connect(ipAddress, port);
            stream = tcpClient.GetStream();

            IPAddress IP = IPAddress.Parse(ipAddress);
            udpEndPoint = new IPEndPoint(IP, port);

            udpSocket.Connect(udpEndPoint);

            writer = new BinaryWriter(stream, Encoding.UTF8);
            reader = new BinaryReader(stream, Encoding.UTF8);

        }
        catch
        {
            return false;
        }

I then send a TCP packet to the server containing the endpoint of the client. Server side has it's own client objects which also have an endpoint so when the server receives the packets, I assign the endpoint to the corresponding client object on the server side.


case PacketType.CONNECTED:
        ConnectedPacket connectedPacket = (ConnectedPacket)packet;
        Console.WriteLine("Player " + connectedPacket.ID + " Has Connected!");

        client.ID = connectedPacket.ID;
        client.AttachUDPEndPoint(connectedPacket.udpEndPoint);

The Server has a UDPCLient which I set up when I create the server, along with connecting it to the same IP and Port I use for my TCP connection. Those being 127.0.0.1 for the IP and 4444 for the port.


try
{
    IPAddress IP = IPAddress.Parse(ipAddress);
    tcpListener = new TcpListener(IP, port);
    udpListener = new UdpClient();
    udpListener.Connect(IP, port);
}
catch (Exception e)
{
    Console.WriteLine(e.ToString());
}

Whenever I want to send a packet to a client, I just call the corresponding client's (on the server side) "SendUDP" function which uses a passed in UDPClient from the Server, the same UDPClient which is set in the code above (udpListener). I just pass that listener from the server whenever I call the function.


public void SendUDP(UdpClient listener, Packet packet)
{
    MemoryStream memoryStream = new MemoryStream();
    formatter.Serialize(memoryStream, packet);

    Byte[] buffer = memoryStream.GetBuffer();
    listener.Send(buffer, buffer.Length, udpEndPoint);
}

player2.SendUDP(udpListener, positionPacket);

Sadly whenever I sent a UDP packet and the client attempts to recieve it, I just get given an error like this:

enter image description here

I get this error on every client and it's coming from a while loop which I use to check for incoming packets:


int noOfIncomingBytes;
			byte[] bytes = new byte[256];
			while (!disconnected && (noOfIncomingBytes = udpSocket.Receive(bytes)) != 0)
			{
				bytes = reader.ReadBytes(noOfIncomingBytes);
				MemoryStream memoryStream = new MemoryStream(bytes);
				Packet packet = formatter.Deserialize(memoryStream) as Packet;

				Console.WriteLine("Client UDP Packet Recieved");

				switch (packet.type)
				{
					case PacketType.POSITIONCHANGE:
						PlayerPositionPacket postionPacket = (PlayerPositionPacket)packet;
						if (postionPacket.playerNumber == 1)
						{
							Vector2 newPos = new Vector2(postionPacket.newPosX, postionPacket.newPosY);
							gameInfo.player1Pos = newPos;
						}
						else if (postionPacket.playerNumber == 2)
						{
							Vector2 newPos = new Vector2(postionPacket.newPosX, postionPacket.newPosY);
							gameInfo.player2Pos = newPos;
						}
					break;
				}
			}

I know the socket can't be set up "that incorrectly" as I'm able to send packets to the server fine, just receiving them is the issue as it seems the listener on the server side isn't connected? When debugging, it's "active" variable is false I'm assuming is bad. 

There is likely a obvious issue in my code somewhere though I'm not sure where (This is my first time ever doing networking). I hope that's enough info to go off of, I'd really appreciate some help.

EDIT: My UDP socket seems to be connected fine when I create my client but as soon as my while loop (The while loop I posted above) that checks to see if it's received any packets runs, it disconnects. 

Advertisement

UDP sockets are generally not connected. If you connect a UDP socket, you say "every packet I send on this socket should go to this particular address," which is usually not what you want. Your server is using Connect() on both TCP and UDP sockets. (Generally, you also don't Connect() on the client, but that's probably not the cause of your current problem.)

When a datagram comes in on a UDP socket, you will also receive the address/port it was sent from. To send a reply, send to the address/port you received the datagram on. The same UDP socket will receive messages from many remote clients, and will thus want to send responses to many remote clients.

Btw: Instead of parsing an IP address and binding the TCP socket, you will typically bind on the "IPADDR_ANY" address (0.0.0.0) so that the user doesn't have to know the IP address of their own machine to open a listening socket.

When it comes to asking for help online, your post is missing some bits, though:

- you say that you get an error, but you don't say whether that error is on the client or the server

- your call to Send is on something called a "listener" which you don't show what it is (you bind a udpListener)

- you don't show the values of the various addresses -- which address values you use matter!

I like it that you're trying to isolate to a small amount of code (posting all your code is even worse!) so take this as a suggestion for how to improve your question-asking skills. (Which end up also improving your debugging skills if you use them on yourself, which in turn will lead to less questions ... virtuous cycle :-D)

 

enum Bool { True, False, FileNotFound };
2 minutes ago, hplus0603 said:

UDP sockets are generally not connected. If you connect a UDP socket, you say "every packet I send on this socket should go to this particular address," which is usually not what you want. Your server is using Connect() on both TCP and UDP sockets. (Generally, you also don't Connect() on the client, but that's probably not the cause of your current problem.)

When a datagram comes in on a UDP socket, you will also receive the address/port it was sent from. To send a reply, send to the address/port you received the datagram on. The same UDP socket will receive messages from many remote clients, and will thus want to send responses to many remote clients.

Btw: Instead of parsing an IP address and binding the TCP socket, you will typically bind on the "IPADDR_ANY" address (0.0.0.0) so that the user doesn't have to know the IP address of their own machine to open a listening socket.

When it comes to asking for help online, your post is missing some bits, though:

- you say that you get an error, but you don't say whether that error is on the client or the server

- your call to Send is on something called a "listener" which you don't show what it is (you bind a udpListener)

- you don't show the values of the various addresses -- which address values you use matter!

I like it that you're trying to isolate to a small amount of code (posting all your code is even worse!) so take this as a suggestion for how to improve your question-asking skills. (Which end up also improving your debugging skills if you use them on yourself, which in turn will lead to less questions ... virtuous cycle :-D)

 

Yea... I've never been good at asking questions based on programming, though I appreciate that you're nice about it instead of very direct and mean xD (Like a lot of people on Stack Overflow). I've updated my main post to add the information you mentioned so I hope that improves it :) 

 

That sounds like an icmp disconnect exception.  You can ignore my ramblings in this post, but there's a couple of useful links and a bit of code that may help you out here.

 

4 hours ago, Septopus said:

That sounds like an icmp disconnect exception.  You can ignore my ramblings in this post, but there's a couple of useful links and a bit of code that may help you out here.

 

This is the full error message: 

System.Net.Sockets.SocketException
  HResult=0x80004005
  Message=An existing connection was forcibly closed by the remote host
  Source=System
  StackTrace:
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.Socket.Receive(Byte[] buffer)
   at Pong___Concurrent_Networking.PlayerUtils.Client.UDPProcessServerResponse(Object client) in C:\Users\codel\Documents\Visual Studio 2017\Projects\Pong-Concurrent-Networking\Pong - Concurrent Networking\PlayerUtils\Client.cs:line 185
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart(Object obj)
 

1 hour ago, Codelyy said:

This is the full error message: 

System.Net.Sockets.SocketException
  HResult=0x80004005
  Message=An existing connection was forcibly closed by the remote host
  Source=System
  StackTrace:
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.Socket.Receive(Byte[] buffer)
   at Pong___Concurrent_Networking.PlayerUtils.Client.UDPProcessServerResponse(Object client) in C:\Users\codel\Documents\Visual Studio 2017\Projects\Pong-Concurrent-Networking\Pong - Concurrent Networking\PlayerUtils\Client.cs:line 185
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart(Object obj)
 

Which is why I linked that article.  Check the links and code within it to see if it solves your problems. ;)

Edit:  Sorry for the terse response, I'm not the best one to describe this issue in detail.  But basically even though you are using UDP, Windows is still listening to ICMP messages regarding the connection attempts and failures.  In some scenarios this will cause all sorts of trouble for Windows netcode.  This is a special Windows only kind of issue, at least the fix is windows only, and my code(somewhat similar to yours) doesn't need it when running on Linux.

Just try using the code snip from the article and see if it alleviates the issue.  And if not, you may need it anyhow.  Hope it helps.

 

Assuming that it is related to an ICMP/disconnect/reconnect issue:

Another thing to note is that, it may be possible to resolve this issue by making sure that client connections are cleaned up proactively on the server side.  Instituting a keep-alive period, and having the server close client connections semi-aggressively can limit the effect of dropped connections on reconnect attempts. ;)

1 minute ago, Septopus said:

Assuming that it is related to an ICMP/disconnect/reconnect issue:

Another thing to note is that, it may be possible to resolve this issue by making sure that client connections are cleaned up proactively on the server side.  Instituting a keep-alive period, and having the server close client connections semi-aggressively can limit the effect of dropped connections on reconnect attempts. ;)

I tried what you mentioned in that post you posted above and it still didn't work. 

I honestly don't think it's anything like that. I just think I'm setting up my UDP wrong since as I've never actually implemented UDP before. 

Just now, Codelyy said:

I tried what you mentioned in that post you posted above and it still didn't work. 

I honestly don't think it's anything like that. I just think I'm setting up my UDP wrong since as I've never actually implemented UDP before. 

Well, it was worth a try..  Same error message so.. ;)

3 minutes ago, Septopus said:

Well, it was worth a try..  Same error message so.. ;)

It's very strange since I'm able to send UDP packets from the client to the server and have the server's UDPClient pick them up fine, But I have issues when sending UDP packets from the server to the client so it's either that the UDPClient on the server side can't send any UDP packets back to the client, or the clients socket can't pick up any of the UDP packets. 

This topic is closed to new replies.

Advertisement