I need a simple connectionless ClientServer application to exchange a bunch of information with a wireless device.
Before to talk about problems I'll show what I've till now:
Environment: C#, WPF, .NetFramework 4.7.1, Visual Studio 2017
Logical Organization: UDP -> UDPServer -> UDPSpecServer; UDP -> UDPClient
Code:
// Server App ctor
endPoint = new IPEndPoint(IPAddress.Any, 0);
socket.Bind(new IPEndPoint(ip, connPort));
which should basically means that I accepts packets from everyone at specified ip (localhost) / port (1984). At some point in the code I have:
public void StartReceivingConnectionless()
{
IAsyncResult result;
try
{
result = socket.BeginReceiveFrom(buffer, 0, MAX_UDP_PACKET_DIMENSION, SocketFlags.None, ref endPoint, new AsyncCallback(MessageReceived), buffer);
}
catch(Exception exception)
{
System.Diagnostics.Debug.Print(exception.Message);
}
}
which should basically means that my server object starts to wait for incoming data, while the MessageReceived method:
public virtual void MessageReceived(IAsyncResult asynchronousResult)
{
int bytes = socket.EndReceiveFrom(asynchronousResult, ref endPoint);
StartReceivingConnectionless();
}
And finally, for Serverside:
public void StopReceivingConnectionless()
{
socket.Close();
}
While on client:
// Clientapp ctor
client = new FST.Lib.NetworkCommunication.UDPClient("localhost", "0");
// On-click somewhere
client.SendConnectionless(Encoding.ASCII.GetBytes("Hello world"), new System.Net.IPEndPoint(System.Net.IPAddress.Parse("127.0.0.1"), 1984));
1) I still have to undesterstand why/how, but sometimes the app works, sometimes no: why?
2) The stopreceveing method is placed in the "Window_closing" event of main window, no matter what, it generates a disposed object exception because it generate a message which is recevied. Where should I put it?
For part 1) - it seems that my Virtual Machines was the problem. I replicated the same library at home and everything went fine. In this case, I solved using UdpClient with less or more the same architecture.
Part 2) is still a partial puzzle: I was missing the call to socket.Shutdown(); and then socket.Close(); as pointed out here but this call generates a message received from the same socket causing the crash.
I'm accepting this answer, but more detailed ones are still welcome.
Related
I am using Console application as a server on windows 10 Pro.
Android application made with Unity Engine as Client.
For both application I use TCP socket on the .Net framework.
Note: the server is always running on wire connection.
Everything work pretty well on both wire and Wi-Fi connections with no problem no meter how packet length is.
The Problem
Each evening the cellular network became too bad and the client app receive only part of the data when the data is little bigger about 50 kb
The code on the server side:
_socket.Send(Encoding.ASCII.GetBytes(s));
_socket: is an instance System.Net.Sockets.Socket.
s: is string.
The code on the client side:
public static void ReceiveData()
{
message = string.Empty;
_socket.BeginReceive(globalBuffer, 0, globalBuffer.Length, SocketFlags.None, ReceiveCallBack, null);
}
public static void ReceiveCallBack(IAsyncResult ar)
{
int internalBuffer = _socket.EndReceive(ar);
byte[] subtractedBuffer = new byte[internalBuffer];
Array.Copy(globalBuffer, subtractedBuffer, internalBuffer);
string stmp = Encoding.ASCII.GetString(subtractedBuffer);
message += stmp;
while (message.Contains("</Cargo>"))
{
string stringOne = message.Substring(0, message.IndexOf("</Cargo>") + "</Cargo>".Length);
string stringLeft = message.Substring(message.IndexOf("</Cargo>") + "</Cargo>".Length);
message = stringLeft;
Thread thread = new Thread(TreatOrder);
thread.Start(stringOne);
}
if (!(_socket.Poll(1000, SelectMode.SelectRead) && _socket.Available == 0))
{
NetWorkScript.LastConnectedTime = DateTime.Now;
_socket.BeginReceive(globalBuffer, 0, globalBuffer.Length, SocketFlags.None, ReceiveCallBack, null);
}
else
{
Debug.log("Connection lost");
}
}
What I have notice:
The next line of code never executed
else
{
Debug.log("Connection lost");
}
The server keep receiving messages from the client on the same Socket instance by another thread and that is how came to know the connection is not broken unless TCP connection could be broken on one way only.
What I understand so far
The TCP will make sure the packets will arrive at the exact order.
The next line of code in my server application end its responsibility and the Operation System will carry on the mission to send the data.
_socket.Send(Encoding.ASCII.GetBytes(s));
What I am confused about
How the Operation System will deliver the data to the client?, why it is not keep trying until send all the data if the connection still exist?
Should I created my own protocol and send small packet then retransmit if client does not confirm receiving the packet?
I'm trying to write a chat client/server in c# locally to get familiar with Sockets.
First I start the server with (very simplified) following code:
Server.cs
private readonly MessageManager _messageManager;
private readonly ChatServer _chatServer;
public ChatServerSkeleton()
{
_messageManager = new MessageManager();
_chatServer = new ChatServer();
Console.WriteLine("Server is running on: " + _messageManager.MyAddress);
}
Then I start the Client with +- same way, except I store the serveraddress in the client (I copied the server address into a prompt).
Client.cs
private readonly MessageManager _messageManager;
public ChatClient ChatClient { get; }
public ChatClientSkeleton(IPEndPoint serverAddress, string name)
{
_messageManager = new MessageManager();
ChatClient = new ChatClient(new ChatServerStub(serverAddress, _messageManager), name);
Console.WriteLine($"IPAddress of {name} is: {_messageManager.MyAddress}");
Console.WriteLine($"IPAddress of Server is: { serverAddress}");
}
MessageManager.cs
private readonly TcpListener _serverSocket;
public IPEndPoint MyAddress { get; }
public MessageManager()
{
try
{
//Create server socket on random port
_serverSocket = new TcpListener(IPAddress.Any, FindFreeTcpPort());
//Get host ip address
IPAddress[] localIps = Dns.GetHostAddresses(Dns.GetHostName());
IPAddress localhost = localIps.First(ip => ip.AddressFamily == AddressFamily.InterNetwork);
//Get port of serversocket
IPEndPoint ipEndPoint = _serverSocket.LocalEndpoint as IPEndPoint;
int port = ipEndPoint.Port;
//Create address
MyAddress = new IPEndPoint(localhost, port);
}
catch (Exception ex)
{
Console.Error.WriteLine("Something went wrong with the serversocket:");
Console.Error.WriteLine(ex);
}
}
FindFreeTcp port comes from here: https://stackoverflow.com/a/150974/5985593
Everything up till now seems to work. Let's say for example the server has now 192.168.0.219:51080 and the client 192.168.0.219:51085.
The problem occurs when I'm trying to send a message using this code in MessageManager.cs
public void Send(MethodCallMessage message, IPEndPoint address)
{
try
{
_serverSocket.Start();
TcpClient destination = new TcpClient(address.Address.ToString(), address.Port);
NetworkStream output = destination.GetStream();
MessageReaderWriter.Write(message, output);
destination.Close();
}
catch (Exception ex)
{
Console.Error.WriteLine("Failed to write a message:");
Console.Error.WriteLine(ex);
}
finally
{
_serverSocket.Stop();
}
}
More specific on the _server.Start(); line.
Anyone knows what I'm doing wrong?
Thanks in advance!
EDIT: it runs fine 1 time, when registering the client on the server. But after that if I want to send a message I get the SocketException where target machine actively refused.
I do use AcceptTcpClient() here:
MessageManager.cs
public MethodCallMessage WReceive()
{
MethodCallMessage result = null;
try
{
//_serverSocket.Start();
TcpClient client = _serverSocket.AcceptTcpClient();
NetworkStream input = new NetworkStream(client.Client, true);
result = MessageReaderWriter.Read(input);
client.Close();
}
catch (Exception ex)
{
Console.Error.WriteLine("Failed to receive a message:");
Console.Error.WriteLine(ex);
}
finally
{
//_serverSocket.Stop();
}
return result;
}
This method is used in the ServerSkeleton & ClientSkeleton as follows:
public void Run()
{
while (true)
{
MethodCallMessage request = _messageManager.WReceive();
HandleRequest(request);
}
}
So the flow is basically as follows:
I start the server (instantiate new messagemanager, 3rd snippet
and run serverskeleton (last snippet)
Server prints IP in
console, i copy the ip & start the client
Instantiate client &
set server ip to what I copy pasted
Start client skeleton (last
snippet)
A TcpListener that has called Start() listens for incoming connections and then stacks them on a queue. Once that queue is full then a socket exception results. To remove connections from the queue you need to use the AcceptTcpClient or AcceptSocket methods of TcpListener. This then gives you a connection that you can send and receive data on.
What I am guessing may be happening is that you receive your first incoming client, but dont accept and remove it to send and receive data on, and your subsequent connections are refused as the pending queue list is full (this is just a guess).
There is an overloaded method ... TcpListener.Start(int backlog) ... that allows you to set the size of the pending queue list (so you can have 5, 10 or more connections waiting to be accepted in the TcpListener)
With a server TCP socket the process is that you set it listening on a local address and a port. Clients then try to connect to that endpoint. When they connect the TCP listening socket accepts the connection and then passes that to a socket which is the socket on which data is transfered. The listening socket carries on listening for new connections, it doesnt itself transmit data.
I hope that makes sense ?
So the server would behave more like this ...
_serverSocket.Start();
TcpClient myAcceptedConnection = _serverSocket.AcceptTcpClient();
// in synchronous blocking socket situation the program flow halts
// here til a connection is established
// once you have a connection ... do stuff with myAcceptedConnection
if you wished to avoid the blocking scenario you can use TcpListener.Pending() to see if you have any connections waiting in the queue
EDIT 1:
Ok so the only weird thing I see is that you call the _serverSocket.Start() method in the MessageSend method ? A server doesnt normally start by sending out a message ... it normally waits listening for a connection, receives and reads the connection and then replies (or it might send out a greeting or such on connection).
Personally I would separate the listening aspect of the server from the sending and receiving of data ... have it in its own separate method, after all you want your server to be listening for incoming connections until you close it down. When you detect an incoming connection (perhaps by checking Pending() in a loop), then you can accept it and send and receive on the new TcpClient. When you are finished with whatever data you are transmitting/receiving on that client you can close it down , if thats what you want ... you dont need to close and open a tcp connection every time you send a message, you can leave it open til you are finished with it, in fact opening and closing tcp connections generates a bit of overhead in the handshake protocol that they go through.
There are caveats though ... Tcp connections can become "half open" especially with wireless which can lead to issues. Its a bit complicated to get into here, but I recommend this stellar set of articles by Stephen Cleary as a good read through. Read the whole blog, as there is a ton of good info in there.
So, back to simple, I would have ...
A serverStart() method where you start your server listening.
A serverAccept() method where you check if you have any pending connections and accept them if they are there.
A clientConnect() method for your client where you connect to a server
Read() and Write() methods for the server and the client where you do the data transmission.
Normally the flow would be ...
Server Listens
Client Connects
Server Accepts
Client Sends
Server Receives
(then server sends/receives, client sends/receives)
everything closes and shuts down
Hello everyone I am very new to Visual Studio, C# programming, and Windows Form Applications.
My need is very simple - I want to create my own small program to listen to data being sent by a GPS device over UDP. I do not need to communicate, just listen and see the data on the screen!
Something that works exactly the same as this :
http://sockettest.sourceforge.net/ (see 'UDP' tab)
My GPS device has an IP of 192.168.1.1 and sends a sting of numbers every 1 second, continuously, transmitting on UDP 25.255.255.255:5017.
All the examples on the internet seems to focus on 2-way communicate, client and server chat windows etc. There is a lot of confusing terminology like synchronous and a-synchronous, client, server, UDP, TCP, binding.
I just want an even more simplified program than the above example, where I can type in the port number 5017, click Start Listening, and then straight away works!
All advice and code examples very gratefully received!!
Many thanks,
Jon
I now have it working, and can receive data in a textbox in the UI!
I use button_start_Click to open the port and start receiving. However, I cannot get button_stop_Click to work. How can you stop/close/disconnect/endReceive using button click?
public Form1()
{
InitializeComponent();
}
private void button_start_Click(object sender, EventArgs e)
{
Client = new UdpClient(Convert.ToInt32(textBox_port.Text));
Client.BeginReceive(DataReceived, null);
}
private void DataReceived(IAsyncResult ar)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, Convert.ToInt32(textBox_port.Text));
byte[] data;
try
{
data = Client.EndReceive(ar, ref ip);
if (data.Length == 0)
return; // No more to receive
Client.BeginReceive(DataReceived, null);
}
catch (ObjectDisposedException)
{
return; // Connection closed
}
// Send the data to the UI thread
this.BeginInvoke((Action<IPEndPoint, string>)DataReceivedUI, ip, Encoding.UTF8.GetString(data));
}
private void DataReceivedUI(IPEndPoint endPoint, string data)
{
txtLog.AppendText("[" + endPoint.ToString() + "] " + data + Environment.NewLine);
}
private void button_stop_Click(IAsyncResult ar) // NOT WORKING!! AGH!
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, Convert.ToInt32(textBox_port.Text));
byte[] data;
data = Client.EndReceive(ar, ref ip);
Client.Close();
}
Run the same code in background worker and then you can cancel the background worker anytime using backgroundworker.cancelasync().
Hope this helps.
I'm trying to send and receive to/from a UDP multicast address using UWP. It works perfectly the first few times, but after a while of this send-receive process, it will lock on the receiving part. I changed from an async approach to a synchronous one but still the same. Even if I instantiate a new UDP client, the port is blocked until the app is restarted. Anything I'm doing wrong?
private UdpClient udp;
//inside main function:
if (udp == null)
{
udp = new UdpClient(new IPEndPoint(IPAddress.Any, portNumber));
//^the second time this is called, it will complain about port reuse
udp.Client.ReceiveTimeout = udp.Client.SendTimeout = 3000;
//udp.Client.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.ReuseAddress, true);
//^invalid
}
//await udp.SendAsync(data, data.Length, , portNumber);
//I changed from async to synchronous in case it was the issue, but no.
udp.Client.SendTo(data, new IPEndPoint(IPAddress.Parse(ipString), portNumber));
//the receive used to be async, too
byte[] receivedByte = new byte[udp.Client.ReceiveBufferSize];
try
{
udp.Client.Receive(receivedByte);
}
catch (Exception ex)
{
udp.Client.Shutdown(SocketShutdown.Both);
udp = null; // added these, but port still blocked until restart
}
I'm using UWP, and there are methods on class library that aren't here.
After putting UdpClient in a using () statement instead of declaring it as a private field, and limiting its scope by putting it in a short async method, I am not having these problems anymore.
Using the following code:
HttpListener listener = new HttpListener();
//listener.Prefixes.Add("http://*:80/");
listener.Prefixes.Add("http://*:8080/");
listener.Prefixes.Add("http://*:8081/");
listener.Prefixes.Add("http://*:8082/");
listener.Start();
HttpListenerContext context = listener.GetContext();
HttpListenerRequest request = context.Request;
The program hangs on the GetContext(); despite loading http (not https) pages in IE and Firefox.
When I uncomment the first line I get the error:
Failed to listen on prefix 'http://*:80/' because it conflicts with an
existing registration on the machine.
So how do I listen to a browser's requests?
#L.B I want to write a "proxy"
Don't reinvent the wheel and just use the FiddlerCore
public class HttpProxy : IDisposable
{
public HttpProxy()
{
Fiddler.FiddlerApplication.BeforeRequest += FiddlerApplication_BeforeRequest;
Fiddler.FiddlerApplication.Startup(8764, true, true);
}
void FiddlerApplication_BeforeRequest(Fiddler.Session oSession)
{
Console.WriteLine(String.Format("REQ: {0}", oSession.url));
}
public void Dispose()
{
Fiddler.FiddlerApplication.Shutdown();
}
}
EDIT
You can start with this rectangular wheel :)
void SniffPort80()
{
byte[] input = new byte[] { 1 };
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
socket.Bind(new IPEndPoint(IPAddress.Broadcast, 80));
socket.IOControl(IOControlCode.ReceiveAll, input, null);
byte[] buffer = new byte[0x10000];
Task.Factory.StartNew(() =>
{
while (true)
{
int len = socket.Receive(buffer);
if (len <= 40) continue; //Poor man's check for TCP payload
string bin = Encoding.UTF8.GetString(buffer, 0, len); //Don't trust to this line. Encoding may be different :) even it can contain binary data like images, videos etc.
Console.WriteLine(bin);
}
});
}
this port is probably being used...
run netstat -ano on the command line, youll see list of the ports that are being used and the their process ids.
I dont know, why the GetContext(); hangs, because there is too less information about what happens with the listerner variable, but the problem with port 80 usually is caused by Skype, because it uses port 80 by default. To fix that, open Skype's preferences, go to advanced->connection and uncheck "Use Port 80 and 443 as an alternative for incoming Connections".
I would consider looking into this package http://www.nuget.org/packages/Microsoft.AspNet.WebApi.OwinSelfHost/
It uses HttpListener under the covers and with the WebApi HttpMessageHandler it is very easy to create a proxy.
It hangs because GetContext() is waiting for a request to be received, as said in its documentation:
This method blocks while waiting for an incoming request. If you want incoming requests to be processed asynchronously (on separate threads) so that your application does not block, use the BeginGetContext method.
For more info see: https://msdn.microsoft.com/en-us/library/system.net.httplistener.getcontext(v=vs.110).aspx
Using Asynchronous model tends to be complex, another alternative is running all that code in a different Thread but it depends on your goals.
Replace * in your prefixes with +
listener.Prefixes.Add("http://+:8080/");