Socket Programming c# / Client-Server communication - c#

I am trying to make 2 programs (in console application) in .NET that communicate together through the web (the code is from a video that you can find below, I am just trying to make the code work before adapting it). Forgive me, I'm not an experienced programmer.
I have a server and a client, they work perfectly when I run both of them on my computer (locally).
I can connect multiple clients to the server, send requests and get a response.
I am facing the problem when i run the server on a computer and the client on an other one and I try to connect through the internet.
I can connect to the server but communication does not work, there is no data exchange when try to request time as an example. I think that the problem is mostly coming from the network itself than the code.
Here's the code for the server:
class Program
{
private static Socket _serverSocket;
private static readonly List<Socket> _clientSockets = new List<Socket>();
private const int _BUFFER_SIZE = 2048;
private const int _PORT = 50114;
private static readonly byte[] _buffer = new byte[_BUFFER_SIZE];
static void Main()
{
Console.Title = "Server";
SetupServer();
Console.ReadLine(); // When we press enter close everything
CloseAllSockets();
}
private static void SetupServer()
{
// IPAddress addip = GetBroadcastAddress();
Console.WriteLine("Setting up server...");
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(new IPEndPoint(IPAddress.Any , _PORT));
_serverSocket.Listen(5);
_serverSocket.BeginAccept(AcceptCallback, null);
Console.WriteLine("Server setup complete");
}
/// <summary>
/// Close all connected client (we do not need to shutdown the server socket as its connections
/// are already closed with the clients)
/// </summary>
private static void CloseAllSockets()
{
foreach (Socket socket in _clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
_serverSocket.Close();
}
private static void AcceptCallback(IAsyncResult AR)
{
Socket socket;
try
{
socket = _serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets)
{
return;
}
_clientSockets.Add(socket);
socket.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
Console.WriteLine("Client connected, waiting for request...");
_serverSocket.BeginAccept(AcceptCallback, null);
}
private static void ReceiveCallback(IAsyncResult AR)
{
Socket current = (Socket)AR.AsyncState;
int received;
try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
Console.WriteLine("Client forcefully disconnected");
current.Close(); // Dont shutdown because the socket may be disposed and its disconnected anyway
_clientSockets.Remove(current);
return;
}
byte[] recBuf = new byte[received];
Array.Copy(_buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);
Console.WriteLine("Received Text: " + text);
if (text.ToLower() == "get time") // Client requested time
{
Console.WriteLine("Text is a get time request");
byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
current.Send(data);
Console.WriteLine("Time sent to client");
}
else if (text.ToLower() == "exit") // Client wants to exit gracefully
{
// Always Shutdown before closing
current.Shutdown(SocketShutdown.Both);
current.Close();
_clientSockets.Remove(current);
Console.WriteLine("Client disconnected");
return;
}
else
{
Console.WriteLine("Text is an invalid request");
byte[] data = Encoding.ASCII.GetBytes("Invalid request");
current.Send(data);
Console.WriteLine("Warning Sent");
}
current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
}
}
And here the client code:
class Program
{
private static readonly Socket _clientSocket = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private const int _PORT = 50114;
static void Main()
{
Console.Title = "Client";
ConnectToServer();
RequestLoop();
Exit();
}
private static void ConnectToServer()
{
int attempts = 0;
while (!_clientSocket.Connected)
{
try
{
attempts++;
Console.WriteLine("Connection attempt " + attempts);
_clientSocket.Connect("IpAddr", _PORT);
}
catch (SocketException)
{
Console.Clear();
}
}
Console.Clear();
Console.WriteLine("Connected");
}
private static void RequestLoop()
{
Console.WriteLine(#"<Type ""exit"" to properly disconnect client>");
while (true)
{
SendRequest();
ReceiveResponse();
}
}
/// <summary>
/// Close socket and exit app
/// </summary>
private static void Exit()
{
SendString("exit"); // Tell the server we re exiting
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Close();
Environment.Exit(0);
}
private static void SendRequest()
{
Console.Write("Send a request: ");
string request = Console.ReadLine();
SendString(request);
if (request.ToLower() == "exit")
{
Exit();
}
}
/// <summary>
/// Sends a string to the server with ASCII encoding
/// </summary>
private static void SendString(string text)
{
byte[] buffer = Encoding.ASCII.GetBytes(text);
_clientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
}
private static void ReceiveResponse()
{
var buffer = new byte[2048];
int received = _clientSocket.Receive(buffer, SocketFlags.None);
if (received == 0) return;
var data = new byte[received];
Array.Copy(buffer, data, received);
string text = Encoding.ASCII.GetString(data);
Console.WriteLine(text);
}
}
static void Main()
{
Console.Title = "Client";
ConnectToServer();
RequestLoop();
Exit();
}
private static void ConnectToServer()
{
int attempts = 0;
while (!_clientSocket.Connected)
{
try
{
attempts++;
Console.WriteLine("Connection attempt " + attempts);
_clientSocket.Connect("IpAddr", _PORT);
}
catch (SocketException)
{
Console.Clear();
}
}
Console.Clear();
Console.WriteLine("Connected");
}
"IpAddr" is a placeholder for the public IP of the router.
This is the video my current code is based on: https://www.youtube.com/watch?v=xgLRe7QV6QI
I took the code directly from it (you can find the 2 code files on the site linked in description).
I run the server, it awaits for a connection. I then run the clients which tries to connect to the server. I connects and on the server it shows the successful connection. The client then sends a request like "get time" and the server is supposed to catch it and respond:
byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
current.Send(data);
Back to network side:
Here is a list of all the things I have tried, that were the usual main causes of the problem after looking for a solution for about a full day:
I already have a static public IP for the router (so the public IP never changes). Even though, I created a dynamic dns on noip.com.
I gave a static lease to the computer the server runs on, so it has always the same local ip.
I created rules in the windows firewall to make sure the port I use is opened. I did this on both computers trying to communicate.
I forwarded the port on the router so it points to the local ip of the computer the server runs on. (I tried with a lot of different ports, no chance)
I tried activating the "DMZ" on the router but it's most likely not a solution
I tried to create a ASP.NET website which page returns a string, publish it with IIS 7.5 and set it up. Works on localhost but using the public ip like "xx.xxx.xxx.xx:PORT/default/index" I get an error. Yet it shows the website name in the error. Also, when using the local IP of the computer, it doesn't work either (something like 192.168.1.180).
Thanks for you help.

I learned about message framing, Thank you CodeCaster.
For people who are curious about it, here is an interesting link i found about it: http://blog.stephencleary.com/2009/04/message-framing.html
But before trying to change the code, I ran the server on an AWS vps and it worked instantly, the problem was probably comming from my isp or my router. I am just wondering how can it work without handling message framing.

Related

TcpClient only connects if server starts listening before ConnectAsync called

I have a basic TCP client and server both running locally on my machine.
If the server is already listening when I call ConnectAsync() then the client connects to the server, no problem.
If I start up the client and call ConnectAsync(), THEN start the server after to listen to clients, it doesn't establish a connection. ConnectAsync hangs for about 85 seconds before I get the following error: System.Net.Sockets.SocketException (0x80004005): Connection refused. This is despite the fact that the server has already started listening.
Not sure if this affects TcpClient but the client is running in an Xamarin project.
Here is my code:
CLIENT:
public static class DataSource
{
private static TcpClient client;
private static NetworkStream networkStream;
public static bool Connected => client is null ? false : client.Connected;
public static async Task EstablishTcpConnection(string serverIP, int port)
{
CloseTcpConnection();
try
{
client = new TcpClient();
await client.ConnectAsync(IPAddress.Parse(serverIP), port);
networkStream = client.GetStream();
}
catch (Exception ex)
{
Console.WriteLine($"{nameof(EstablishTcpConnection)} Error: {ex}");
}
}
public static void CloseTcpConnection()
{
if (networkStream != null)
{
networkStream.Close();
networkStream.Dispose();
networkStream = null;
}
if (client != null)
{
client.Close();
client.Dispose();
client = null;
}
}
public static async Task SendTcp(string toSend)
{
if (client is null) return;
if (networkStream is null) return;
if (!Connected) return;
if (networkStream != null && networkStream.CanWrite)
{
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(toSend);
await networkStream.WriteAsync(bytesToSend, 0, bytesToSend.Length);
}
}
public static async Task TcpListener()
{
while (networkStream != null && networkStream.CanRead)
{
if (client is null) return;
if (networkStream is null) return;
if (!Connected) return;
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = await networkStream.ReadAsync(bytesToRead, 0, client.ReceiveBufferSize);
string received = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead);
Console.WriteLine($"Received: {received}");
}
}
}
SERVER:
internal class Program
{
private const string serverIP = "MyServerIp";
private const int port = myPort;
private static void Main(string[] args)
{
Listener();
Console.ReadLine();
}
public static async Task Listener()
{
//---listen at the specified IP and port no.---
TcpListener listener = new TcpListener(IPAddress.Parse(serverIP), port);
listener.Start();
Console.WriteLine("Listening...");
while (true)
{
//---incoming client connected---
ReceiveClient(await listener.AcceptTcpClientAsync());
}
}
public static async Task ReceiveClient(TcpClient client)
{
if (client is null) return;
Console.WriteLine("Client Connected");
//---get the incoming data through a network stream---
NetworkStream networkStream = client.GetStream();
byte[] buffer = new byte[client.ReceiveBufferSize];
while (client != null && client.Connected)
{
//---read incoming stream---
int bytesRead = await networkStream.ReadAsync(buffer, 0, client.ReceiveBufferSize);
if (bytesRead == 0) break;
//---convert the data received into a string---
string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("Received : " + dataReceived);
//---write back the text to the client---
Console.WriteLine("Sending back : " + dataReceived);
networkStream.Write(buffer, 0, bytesRead);
}
client.Close();
client.Dispose();
Console.WriteLine("Client Disconnected");
}
}
Surely ConnectAsync() should still work, even if the server starts listening after and is within the timeout?
No; that's not what "timeout" means. "Timeout" does not imply a "retry".
When you establish a connection, your client app is reaching out to the server app running on a server computer. The "timeout" is just the amount of time the client app will wait for a response. If the server computer is running, but doesn't have a listening server app for that port, then the server computer will immediately send a response indicating that there is no server app running. This gets sent back to your client app. This is a valid "response", so the timeout doesn't come into play.
If you want to retry connections, waiting for a server, then you'll need to write that logic yourself.
If you're running both programs on the same computer, it's likely that the ConnectAsync() request is rejected before the server is initialised. This happens because there’s no process listening on the incoming port. So the OS rejects the connection request.
Check the type of exception being thrown. If it's a SocketException, its SocketErrorCode property will shed more light on why the connection failed.
A complete list of error codes and their descriptions is available on the Microsoft website at https://learn.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2.

TCP Socket Server custom class for socket identifier in C#

I've been looking at many tcp client/server examples and would want to know how one can go about creating a method to identify each client. One way I know is through lets say, a log in authentication. I know how to connect, and query a database, but how would I lets say after successful authentication, take the username and say this username is this socket. A class example or simple method would be appreciated as an example. I want to be able to target all connected clients by their username from a database individually.
Example I'm using for server
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace MultiServer
{
class Program
{
private static readonly Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private static readonly List<Socket> clientSockets = new List<Socket>();
private const int BUFFER_SIZE = 2048;
private const int PORT = 100;
private static readonly byte[] buffer = new byte[BUFFER_SIZE];
static void Main()
{
Console.Title = "Server";
SetupServer();
Console.ReadLine(); // When we press enter close everything
CloseAllSockets();
}
private static void SetupServer()
{
Console.WriteLine("Setting up server...");
serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT));
serverSocket.Listen(0);
serverSocket.BeginAccept(AcceptCallback, null);
Console.WriteLine("Server setup complete");
}
/// <summary>
/// Close all connected client (we do not need to shutdown the server socket as its connections
/// are already closed with the clients).
/// </summary>
private static void CloseAllSockets()
{
foreach (Socket socket in clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
serverSocket.Close();
}
private static void AcceptCallback(IAsyncResult AR)
{
Socket socket;
try
{
socket = serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets)
{
return;
}
clientSockets.Add(socket);
socket.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
Console.WriteLine("Client connected, waiting for request...");
serverSocket.BeginAccept(AcceptCallback, null);
}
private static void ReceiveCallback(IAsyncResult AR)
{
Socket current = (Socket)AR.AsyncState;
int received;
try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
Console.WriteLine("Client forcefully disconnected");
// Don't shutdown because the socket may be disposed and its disconnected anyway.
current.Close();
clientSockets.Remove(current);
return;
}
byte[] recBuf = new byte[received];
Array.Copy(buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);
Console.WriteLine("Received Text: " + text);
if (text.ToLower() == "get time") // Client requested time
{
Console.WriteLine("Text is a get time request");
byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
current.Send(data);
Console.WriteLine("Time sent to client");
}
else if (text.ToLower() == "exit") // Client wants to exit gracefully
{
// Always Shutdown before closing
current.Shutdown(SocketShutdown.Both);
current.Close();
clientSockets.Remove(current);
Console.WriteLine("Client disconnected");
return;
}
else
{
Console.WriteLine("Text is an invalid request");
byte[] data = Encoding.ASCII.GetBytes("Invalid request");
current.Send(data);
Console.WriteLine("Warning Sent");
}
current.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
}
}
}
There's a very simple solution to that when you're using the asynchronous callbacks (though I'd strongly recommend switching to a newer approach, or even better, an existing library - raw TCP is hard to do right).
The callback delegate can point to an instance method. This means you can have something like this:
class Client
{
private readonly Socket socket;
public readonly byte[] ReceiveBuffer = new byte[BUFFFER_SIZE];
public Client(Socket socket)
{
this.socket = socket;
}
public void ReceiveCallback(IAsyncResult AR)
{
// Handle the received data as usual
}
}
And then in your AcceptCallback method, just use a list of Client instead of Socket, and the final BeginReceive call as such:
var client = new Client(socket);
socket.BeginReceive(client.ReceiveBuffer, 0, BUFFER_SIZE, SocketFlags.None, client.ReceiveCallback,
socket);
clients.Add(newClient);
But again, writing custom networking is hard. Use an existing solution if possible - there's plenty to choose from.
Also, the ObjectDisposedExceptions you're getting are because you're doing Shutdown immediately followed by a Close. This is wrong. TCP shutdown is coöperative - you need to wait for the client socket to close before you call Close on your socket. What you're doing is rudely interrupting the connection before it has a chance to resolve itself. Again - TCP is hard to do right, you need to learn how it works very thoroughly.

StreamSocketListener only works once; the second call fails

Any help on the issue below would be highly appreciated. I'm using the StreamSocketListener Class to accept TCP/IP connection on my Raspberry Pi 3 running windows IoT 10 Core.
This is my server code so far:
static string _maintenancePort = "8888";
public async static void StartListening()
{
try
{
StreamSocketListener listener = new StreamSocketListener();
var currentSetting = listener.Control.QualityOfService;
listener.Control.QualityOfService = SocketQualityOfService.LowLatency;
listener.ConnectionReceived += SocketListener_ConnectionReceived;
listener.Control.KeepAlive = true;
await listener.BindServiceNameAsync(_maintenancePort);
}
catch (Exception e)
{
Log.WriteErrorLog(e);
}
}
private static async void SocketListener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
try
{
Log.WriteDebugLog("Incoming data...");
Stream inStream = args.Socket.InputStream.AsStreamForRead();
StreamReader reader = new StreamReader(inStream);
string request = await reader.ReadLineAsync();
if (request != null)
{
Log.WriteDebugLog("Received : " + request);
}
}
catch (Exception e)
{
Log.WriteErrorLog(e);
}
}
I wrote the following client code to connect to the socket. This code runs on another machine.
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
private static String response = String.Empty;
public static Socket client;
public static string SendMessageToClient(string ip, int port, string message, bool expectResponse)
{
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
IPAddress ipAddress = IPAddress.Parse(ip);
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
client = new Socket(ipAddress.AddressFamily,SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
message += "^" + expectResponse.ToString();
// Send test data to the remote device.
Send(client, message);
sendDone.WaitOne();
// Receive the response from the remote device.
if (expectResponse)
{
Receive(client);
receiveDone.WaitOne();
}
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
return response;
}
catch (Exception e)
{
Log.Write(e, false);
return "";
}
}
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Log.WriteSingleMessage(String.Format("Sent {0} bytes to server.", bytesSent), false);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Log.Write(e, false);
}
}
}
The client code is triggered by a button click event. The problem that I'm facing is that the server code above only works once. If I send a message to the server with the client code, the server processes the string perfect. However, if I hit the button a second time, the SocketListener_ConnectionReceived event is triggered but no data is coming in. I've tried several classes for ConnectionReceived but they all behave the same.
I checked with netstat on the Raspberry Pi if the server is listening and it is.
TCP 0.0.0.0:8888 0.0.0.0:0 LISTENING
Even child processes are created for handling the connection as you would expect from an Async calls. The client code closes the socket after it received a message that the data has been send (waitOne()) and the socket on the client machines changes to CLOSE_WAIT.
TCP 10.0.102.10:8888 10.0.100.11:31298 CLOSE_WAIT
TCP 10.0.102.10:8888 10.0.100.11:31299 ESTABLISHED
Can anyone help me out and point me in the right direction as to what I'm doing wrong. any help would be highly appreciated.
You can try to use synchronous methods instead asynchronous methods for socket client. It will work. Please refer to following code:
public void SendMessageToClientSync(string ip, int port, string message, bool expectResponse)
{
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
// This example uses port 11000 on the local computer.
IPAddress ipAddress = IPAddress.Parse(ip);
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket sender = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Connect the socket to the remote endpoint. Catch any errors.
try
{
sender.Connect(remoteEP);
Console.WriteLine("Socket connected to {0}",
sender.RemoteEndPoint.ToString());
// Encode the data string into a byte array.
byte[] msg = Encoding.ASCII.GetBytes(message);
// Send the data through the socket.
int bytesSent = sender.Send(msg);
if(expectResponse)
{
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
Console.WriteLine("Echoed test = {0}",
Encoding.ASCII.GetString(bytes, 0, bytesRec));
}
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
catch (ArgumentNullException ane)
{
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
}
catch (SocketException se)
{
Console.WriteLine("SocketException : {0}", se.ToString());
}
catch (Exception e)
{
Console.WriteLine("Unexpected exception : {0}", e.ToString());
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}

c# udp broadcast package not receiving

I got into UDP and decided to make a small chat just for practice.
I ran into a problem and I can't figure it out myself.
I created two c# console Programs which are exactly the same (Just Port is different)
I send a UDP broadcast package and then want to receive it on the second console program. What happens tho is that the program I send the broadcast from receives it and the other program doesn't. Same happens at the other way round.
I already switched off my firewall --> doesn't change anything.
I post you the whole code, I hope you guys can help me I would really love to keep going! Thank you so much!
class Program
{
const int PORT = 10101;
private static readonly UdpClient udpclient = new UdpClient(PORT);
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Red;
udpclient.EnableBroadcast = true;
//bool for calling async receiver just once
bool receiving = false;
Console.WriteLine("Chat 2");
//to keep while loop running --> change later
bool keepchatting = true;
#region keepchating loop
while (keepchatting)
{
if (!receiving)
{
startlistening();
}
receiving = true;
newmessage();
}
}
#endregion
//new message --> call sendmessage to broadcast text via UDP
public static void newmessage()
{
string msg;
msg = Console.ReadLine();
byte[] message = Encoding.ASCII.GetBytes(msg);
sendmessage(message);
}
//Broadcast text via UDP
public static void sendmessage(byte[] tosend)
{
UdpClient client = new UdpClient();
client.EnableBroadcast = true;
IPEndPoint ip = new IPEndPoint(IPAddress.Parse("255.255.255.255"), PORT);
client.Send(tosend, tosend.Length, ip);
client.Close();
Console.WriteLine("Sent!");
}
static IAsyncResult ar = null;
//Setup Async Receive Method
public static void startlistening()
{
ar = udpclient.BeginReceive(RecievedMessage, new object());
}
//Message
public static void RecievedMessage(IAsyncResult ar)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, PORT);
byte[] bytes = udpclient.EndReceive(ar, ref ip);
string msg = Encoding.ASCII.GetString(bytes);
Console.WriteLine("Received: " + msg);
startlistening();
}
}
I have changed only two parts to your code, on each client set the remote port number of the other client, try this:
On one client:
const int PORT = 10101;
const int PORT_Remote = 10102;
IPEndPoint ip = new IPEndPoint(IPAddress.Parse("255.255.255.255"), PORT_Remote);
On the other client:
const int PORT = 10102;
const int PORT_Remote = 10101;
IPEndPoint ip = new IPEndPoint(IPAddress.Parse("255.255.255.255"), PORT_Remote);
I've wrote an application recently where I was sending socket messages back and forth between two applications on my laptop. I used 127.0.0.1 (default IP address for local host) for the IP address. Could you try that?

UdpClient on local machine

I'm new to C# UDP coding and I have some 'strange' behaviour when using an UDP client locally on my pc.
I want to send UDP data from one port (11000) on my pc to another port (12000) on the same pc.
This is a snippet from my code :
public class MyClass
{
//Creates a UdpClient for reading incoming data.
private UdpClient udpClient;
private Thread thread;
private const String IPADDR = "127.0.0.1";
public MyClass()
{
udpClient = new UdpClient(11000);
udpClient.Connect(IPAddress.Parse(IPADDR), 12000);
this.thread = new Thread(new ThreadStart(this.Execute));
this.thread.Name = "Udp";
this.thread.Start();
SendData("The quick brown fox jumps over the lazy dog");
}
private void Execute()
{
try
{
// Blocks until a message returns on this socket from a remote host.
IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = this.udpClient.Receive(ref remoteIpEndPoint);
Console.WriteLine("Data received");
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public void SendData(String data)
{
Console.WriteLine("Sending...");
try
{
this.udpClient.Send(System.Text.Encoding.ASCII.GetBytes(data), data.Length);
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0}", e.Message));
}
}
}
If I run this, I get an exception :
Sending...
System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.ReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint& remoteEP)
at System.Net.Sockets.UdpClient.Receive(IPEndPoint& remoteEP)
at test.MyClass.Execute() in C:\Temp\test\Class1.cs:line 40
The exception seems to occur on this line :
Byte[] receiveBytes = this.udpClient.Receive(ref remoteIpEndPoint);
At the moment of the SendData(), the Receive is throwing the exception. When not doing the send, I don't get the exception. It looks like the send is causing the receive to return with an exception.
When I use the real ip address of my pc, I have the same behaviour. However, when I use any other ip address, even if it's unassigned to any pc (e.g. 192.168.10.10), it's working well : it sends the string and the Receive() keeps waiting for incoming data.
The error happens because there is no socket open on the port to which you are sending.
For the purposes of simply testing UDP communications, you can fix your code example simply by changing the port to which you are sending. I.e. change the Connect() method call to this:
udpClient.Connect(IPAddress.Parse(IPADDR), 11000);
This will cause the socket to send to itself. Your code will work successfully with just this change.
For the record, here is about the simplest possible demonstration code that uses UdpClient:
UdpClient client = new UdpClient(0, AddressFamily.InterNetwork);
byte[] datagram = Encoding.ASCII.GetBytes("hello world!");
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Loopback, ((IPEndPoint)client.Client.LocalEndPoint).Port);
client.Send(datagram, datagram.Length, ipEndPoint);
datagram = client.Receive(ref ipEndPoint);
Console.WriteLine("Received: \"" + Encoding.ASCII.GetString(datagram) + "\"");
Of course, in a real network I/O situation, you will have two endpoints, each bound to its own local port, sending to the other endpoint's port. So neither your code example, nor this simpler one I present is very useful as an actual working program. But it does allow you to learn some things about how the socket API works.
You are trying to send from one socket (UdpClient which is socket wrapper) to itself. Thats not how the things work in UDP (nor in other IP protocols). You need 2 sockets. One for sending one for receiving. Connect method is poorly named since UDP protocol is conectionless but thats not your fault.
Other than that you need to put socket in listening state before sending to it. So you first need to start thread that listens and then send.
You need to better design your program but this will work:
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
}
}
public class MyClass
{
//Creates a UdpClient for reading incoming data.
private UdpClient udpClient;
private UdpClient recipient;
private Thread thread;
private const String IPADDR = "127.0.0.1";
public MyClass()
{
recipient = new UdpClient(new IPEndPoint(IPAddress.Parse(IPADDR), 12000));
this.thread = new Thread(new ThreadStart(this.Execute));
this.thread.Name = "Udp";
this.thread.Start();
udpClient = new UdpClient(11000);
udpClient.Connect(IPAddress.Parse(IPADDR), 12000);
SendData("The quick brown fox jumps over the lazy dog");
}
private void Execute()
{
try
{
// Blocks until a message returns on this socket from a remote host.
IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Parse(IPADDR), 11000);
Byte[] receiveBytes = this.recipient.Receive(ref remoteIpEndPoint);
Console.WriteLine("Data received: " + Encoding.ASCII.GetString(receiveBytes));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public void SendData(String data)
{
Console.WriteLine("Sending...");
try
{
this.udpClient.Send(System.Text.Encoding.ASCII.GetBytes(data), data.Length);
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0}", e.Message));
}
}
}

Categories