I'm trying to fetch some data, which is streamed via an UDP multicast Server. I've coded an C# WPF Application, where i can enter port and IP-address of server. The connection to the server is established sucessfully and i can receive multiple data packages (between 50-500 packages, varies over every try)
I'm calling the receive function via a dispatcher every 33ms. A longer time between the dispatcher event, does not solve the problem.
After a few seconds the UDPClient looses the connection, no data can be received and cannot be established any more.
Here is the function of the button establishing the connection and starts the dispatcher:
public int connectToArtWelder()
{
if (!checkIPAddress())
{
MessageBox.Show("Please enter a valid IP-Address.", "Wrong IP-Address", MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
string iPString = tB_weldConIP.Text;
int port = Convert.ToInt32(tB_weldConPort.Text);
IPAddress iPAddress = IPAddress.Parse(iPString);
udpClient.Connect(iPAddress, port);
try
{
dispatcherTimer2.Tick += new EventHandler(Receive);
dispatcherTimer2.Interval = new TimeSpan(0, 0, 0, 0, 33);
dispatcherTimer2.Start();
}
catch
{
}
}
return 0;
}
Here is the receive function:
private void Receive(object sender, EventArgs e)
{
try
{
int condition = udpClient.Available;
if (condition > 0)
{
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
var asyncResult = udpClient.BeginReceive(null, null);
asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(10));
if (asyncResult.IsCompleted)
{
byte[] receiveBytes = udpClient.EndReceive(asyncResult, ref RemoteIpEndPoint);
double[] d = new double[receiveBytes.Length / 8];
// Do something with data
}
}
else
{
// The operation wasn't completed before the timeout and we're off the hook
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
Please let me know if somebody got any equal problem or a solution for my problem.
SOLUTION:
I've just removed the
udpClient.Connect(ipAddress, port);
command and now it's running super smoothly.
Related
I'm trying to use generic IP socket objects in .NET. Connecting one of my sockets to another one and sending a few ping-pong messages works just fine.
But now I've implemented a server socket and somehow managed to create Schrödinger's socket.
The server socket handles the incoming connection request just fine, but the connecting socket seems to be connected when I check once but doesn't even have a RemoteEndpoint - though is showing "Connected = true" and it's disconnected when I check the 2nd time.
All sockets are initialized using this function:
private void initSocket() {
if (_socket != null) {
_socket.Dispose();
}
_socket = new Socket(_ownIP.AddressFamily, _socketType, _protocolType);
_socket.Bind(new IPEndPoint(_ownIP, _ownPort));
}
The _socketType is Stream and the _protocolType is Tcp in this case.
The connect function:
public bool connect(string ip, int port, int retries = 3) {
if (_isWaiting) {
throw new InvalidOperationException("Can't connect, when the socket is already waiting for clients.");
}
_wasWaiting = false;
initSocket();
_otherIP = IPAddress.Parse(ip);
_otherPort = port;
IPEndPoint endpoint = new IPEndPoint(_otherIP, _otherPort);
for (int i = 0; i < retries; i++) {
try {
IAsyncResult result = _socket.BeginConnect(endpoint, null, null);
bool success = result.AsyncWaitHandle.WaitOne(_connectTimeout, true);
if (_socket.Connected) {
_socket.EndConnect(result);
_isConnected = true;
return true;
}
else {
_socket.EndConnect(result);
}
}
catch (SocketException e) {
Console.WriteLine(e.Message);
}
}
return false;
}
The server uses this wait function to accept more clients:
private void wait() {
while (_isWaiting) {
try {
_socket.Listen(1);
var newSocket = _socket.Accept();
var newClient = new IPSocket(newSocket, _socketType, _protocolType, new MessageReceivedDelegate(clientReceivedMessage), true);
_clients.Add(newClient.PartnerIP + ":" + newClient.PartnerPort, newClient);
clientConnected(newClient.PartnerIP, newClient.PartnerPort);
while (true) {
Thread.Sleep(10);
}
}
catch (System.Net.Sockets.SocketException ex) {
//Need to find out which one is thrown when no client for accepting available
if (ex.ErrorCode == 2) {
}
Thread.Sleep(10);
}
catch {
Thread.Sleep(10);
}
}
}
The newSocket variable is connected at first and has a valid RemoteEndpoint, but the socket that's connected doesn't route back to newSocket.
I thought that maybe the connection resets when the server socket tries to accept new sockets, so I added the infinite wait loop - which didn't help.
So why does the connecting socket not have any RemoteEndpoint? (it's shown as null)
Since people usually recommend to accept the connection, handle data, close connection:
I want to keep the connection alive and I have to - not doing this is at the time not a solution that I'd consider.
My socket server is pretty simple so far:
public static void listen()
{
TcpListener server = null;
IPAddress address = IPAddress.Parse("127.0.0.1");
try
{
server = TcpListener.Create(5683);
server.Start();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
}
while (true)
{
Thread.Sleep(10);
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Accepted Client");
Thread thread = new Thread (new ParameterizedThreadStart(SwordsServer.ClientHandler));
thread.IsBackground = true;
thread.Start(client);
}
}
public static void ClientHandler(object c)
{
TcpClient client = (TcpClient)c;
NetworkStream netstream = client.GetStream();
bool connected = true;
while (connected)
{
Thread.Sleep(10);
try
{
byte[] bytes = new byte[client.ReceiveBufferSize];
netstream.Read(bytes, 0, bytes.Length);
Console.WriteLine("got data");
netstream.Write(bytes, 0, bytes.Length);
}
catch (Exception e)
{
connected = false;
Console.WriteLine(e);
Console.WriteLine(e.StackTrace);
}
}
}
My question is, on a conceptual level, how would you keep tabs on each unique client and send updates from other threads to specific clients?
For example, if I have data for a specific client, how do I reach out to that client instead of broadcasting it? Or, if a client is no longer connected, how could I tell?
Thanks in advance for any assistance!
Your implementation for accepting multiple connections creates anonymous clients, meaning after more than 1 connection you wont be able to identify the right client. If identifying is the problem then you can do one thing, have the client send an identifier to the server like "Client1". Create a Dictionary and in your method ClientHandler(), read the identifier from client and add the TCPClient's object in the dictionary.
So the modified code would be something like this:
Dictionary<string, TCPClient> dictionary = new Dictionary<string, TCPClient>();
public static void ClientHandler(object c)
{
TcpClient client = (TcpClient)c;
NetworkStream netstream = client.GetStream();
bool connected = true;
while (connected)
{
Thread.Sleep(10);
try
{
byte[] bytes = new byte[client.ReceiveBufferSize];
//read the identifier from client
netstream.Read(bytes, 0, bytes.Length);
String id = System.Text.Encoding.UTF8.GetString(bytes);
//add the entry in the dictionary
dictionary.Add(id, client);
Console.WriteLine("got data");
netstream.Write(bytes, 0, bytes.Length);
}
catch (Exception e)
{
connected = false;
Console.WriteLine(e);
Console.WriteLine(e.StackTrace);
}
}
}
Do note: Your application should be intelligent enough to dynamically decide on to which client the updates should be sent.
I am new to programming and I am working on an asynchronous client server application.
I can send a message to the server from the client, but when I receive the data to the server (OnDataReceived Method) and try to send the same data back to the client (for testing purposes) I can't.
Not sure what other info I need to give, so please let me know, I don't mean to be vague.
SERVER CODE
public void OnDataReceived(IAsyncResult asyncResult)
{
try
{
SocketPacket socketData = (SocketPacket)asyncResult.AsyncState;
int iRx = 0;
iRx = socketData.currentSocket.EndReceive(asyncResult);
char[] chars = new char[iRx];
Decoder decoder = Encoding.UTF8.GetDecoder();
int charLen = decoder.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);
String receivedData = new String(chars);
//BroadCast(receivedData);
this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => lbxMessages.Items.Add(receivedData)));
//Updated Code
this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => broadcast(receivedData)));
WaitForData(socketData.currentSocket);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\n OnDataRecieved: Socket has been closed\n");
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
public class SocketPacket
{
public Socket currentSocket;
public byte[] dataBuffer = new byte[50];//allowing the 50 digist to be sent at once
}
private void WaitForData(Socket socket)
{
try
{
if (workerCallBack == null)
{
workerCallBack = OnDataReceived;
}
SocketPacket sckPack = new SocketPacket();
sckPack.currentSocket = socket;
socket.BeginReceive(sckPack.dataBuffer, 0, sckPack.dataBuffer.Length, SocketFlags.None, workerCallBack, sckPack);
}
catch(SocketException se)
{
MessageBox.Show(se.Message);
}
}
Updated in response to Andrew's reply
I have a method that will be invoked when a client is connected
private void OnClientConnect(IAsyncResult asyncResult)
{
try
{
//Here we complete/end the Beginaccept() asynchronous call by
//calling EndAccept() - which returns the reference to a new socket object
workerSocket[clientCount] = listenSocket.EndAccept(asyncResult);
//Let the worker socket do the further processing for the just connected client
WaitForData(workerSocket[clientCount]);
//Now increment the client count
++clientCount;
if (clientCount<4)//allow max 3 clients
{
//Adds the connected client to the list
connectedClients.Add(listenSocket);
String str = String.Format("Client # {0} connected", clientCount);
this.Dispatcher.Invoke((Action)(() =>
{
//Display this client connection as a status message on the GUI
lbxMessages.Items.Add(str);
lblConnectionStatus.Content =clientCount + " Connected";
}));
//Since the main Socket is now free, it can go back and wait for
//other clients who are attempting to connect
listenSocket.BeginAccept(OnClientConnect, null);
}
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n");
}
catch (SocketException)
{
HandleClientDisconnect(listenSocket);
}
}
(UPDATED)
ADDED METHOD TO BROADCAST MESSAGE RECEIVED BY SERVER BACK TO CLIENT
public void broadcast(string msg)
{
//foreach (Socket item in connectedClients)
//{
Socket broadcastSocket;
broadcastSocket = workerSocket[0]; //sends message to first client connected
byte[] broadcastBytes = null;
broadcastBytes = Encoding.ASCII.GetBytes(msg);
broadcastSocket.Send(broadcastBytes);
//}
}
There is two sockets involved in server-side TCP communication. First socket is a listening socket and you should use it only for accepting new request. Then every time you accept new request from the client you're getting another socket for every connection.
You trying to send data back via listening socket but not via socket that you accepted.
Sergey has it right. If you're looking to have one server handle multiple clients, then you'll need some sort of ServerTerminal class which can listen for new connections and then setup some sort of "connectedclient" class to handle IO to that socket. Your "OnDataReceived" method would be in the connectedclient class.
In your socket accept routine it should look something like:
private void OnClientConnection(IAsyncResult asyn)
{
if (socketClosed)
{
return;
}
try
{
Socket clientSocket = listenSocket.EndAccept(asyn);
ConnectedClient connectedClient = new ConnectedClient(clientSocket, this, _ServerTerminalReceiveMode);
connectedClient.StartListening();
In the accept routine you're passed a socket - i've named this "clientSocket". This is the socket you want to write to, not the listening socket.
I am making a program in 2 parts.
Part 1: C# server-socket Application running on PC, listening for commands, and acts accordingly.
Part 2: Java client-socket application running on phone, that sends a command to the pc, when a button is pressed.
Currently, i can send commands from the client to the server, and its all good.
But my problem is this: When i send a specific command to the server, i want the server to reply to the client, and the client to read that reply.
Thing just is, when the client tries to read, it time-outs.
Java client program:
class ClientThread implements Runnable
{
public void run()
{
try
{
Socket socket = new Socket(serverIpAddress, serverPort);
socket.setSoTimeout(5000);
while (true)
{
try
{
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
Log.d("Nicklas", "Out it goes");
out.println(Command);
if (Command == "CMD:GetOptions<EOF>")
{
Log.d("Nicklas", "Getting options");
try
{
Log.d("Nicklas", "Line 1");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.d("Nicklas", "Line 2");
String answer = in.readLine();
Log.d("Nicklas", "answer = " + answer );
}
catch (Exception ee)
{
Log.d("Nicklasasasas", ee.toString());
}
}
break;
}
catch (Exception e)
{
Log.d("Nicklas", "CAE = " + e.toString());
break;
}
}
socket.close();
}
catch (ConnectException ee)
{
Log.d("Nicklas", "Kunne ikke forbinde");
}
catch (Exception e)
{
Log.d("Nicklasssssss", e.toString());
}
}
}
This is called with:
Thread cThread = new Thread(new ClientThread());
cThread.start();
And uses the global variable "Command", which will contain different information, depending on what button was pressed.
The program fails on the line "String answer = in.readline();" with the exception "java.net.SocketTimeoutException".
This is the C# Server part of the program:
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
//System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
string Input = (encoder.GetString(message, 0, bytesRead));
Input = Input.Trim();
object[] obj = new object[1];
obj[0] = Input;
if (Input == "CMD:GetOptions<EOF>")
{
try
{
byte[] buffer = encoder.GetBytes("CMD:Accepted");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
MessageBox.Show("Client program asked for reply");
}
catch (Exception e)
{
MessageBox.Show("Oh it no work!: " + e.ToString());
}
}
else
{
Udfor(Input);
}
}
tcpClient.Close();
}
Called with the following, in the Form1()
this.tcpListener = new TcpListener(IPAddress.Any, 4532);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
The C# Server seems to work fine, and does show the messagebox "client program asked for reply"
Anyone who can spot the error?
I figured it out!
The problem was the C#. When the server sent back the command "CMD:Accepted", it never closed the socket, so the android application had no idea of telling if it was done reading! Closing the socket right after flushing + of course not closing it again if i already did, did the trick!
Recently I have tackled a strange behaviour of .Net synchronous receive method. I needed to write an application that has nodes which communicate with each other by sending/receiving data. Each server has a receipt loop which is synchronous, after receiving a serialized class it deserializes and processes it. After that it sends asynchronously this serialized class to some chosen nodes (using AsynchSendTo).
The MSDN clearly says that:
"If you are using a connection-oriented Socket, the Receive method
will read as much data as is available, up to the size of the buffer.
If the remote host shuts down the Socket connection with the Shutdown
method, and all available data has been received, the Receive method
will complete immediately and return zero bytes."
In my case it's not true. There are some random cases when the Receive doesn't block and returns 0 bytes (non-deterministic situtation) right away after establishing connection. I'm 100% sure that the sender was sending at lest 1000 bytes. One more funny fact: when putting Sleep(500) before receive everything works just fine. Hereunder is the receiving code:
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
_listener.Bind(_serverEndpoint);
_listener.Listen(Int32.MaxValue);
while (true)
{
Console.WriteLine("Waiting for connection...");
Socket handler = _listener.Accept();
int totalBytes = 0;
int bytesRec;
var bytes = new byte[DATAGRAM_BUFFER];
do
{
//Thread.Sleep(500);
bytesRec = handler.Receive(bytes, totalBytes, handler.Available, SocketFlags.None);
totalBytes += bytesRec;
} while (bytesRec > 0);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
catch (SocketException e)
{
Console.WriteLine(e);
}
Also the sending part:
public void AsynchSendTo(Datagram datagram, IPEndPoint recipient)
{
byte[] byteDatagram = SerializeDatagram(datagram);
try
{
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.BeginConnect(recipient, ConnectCallback, new StateObject(byteDatagram, byteDatagram.Length, socket));
}
catch (SocketException e)
{
Console.WriteLine(e);
}
}
public void ConnectCallback(IAsyncResult result)
{
try
{
var stateObject = (StateObject)result.AsyncState;
var socket = stateObject.Socket;
socket.EndConnect(result);
socket.BeginSend(stateObject.Data, 0, stateObject.Data.Length, 0, new AsyncCallback(SendCallback), socket);
}
catch (Exception ex)
{
Console.WriteLine("catched!" + ex.ToString());
}
}
public void SendCallback(IAsyncResult result)
{
try
{
var client = (Socket)result.AsyncState;
client.EndSend(result);
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
class StateObject
{
public Byte[] Data { get; set; }
public int Size;
public Socket Socket;
}
My question: am I using the synchronous receive in a wrong way? Why it doesn't block event though there is data to receive?
You're shooting yourself in the foot.
bytesRec = handler.Receive(bytes, totalBytes, handler.Available, SocketFlags.None);
At the very beginning of the connection, Available will be 0, forcing it to return immediately with 0. Instead, you should specify the number of bytes which are free in your buffer (e.g. bytes.Length-totalBytes), then it will also block.
You may have a concurrency problem here. After you accept a connection, you jump straight into receive. The sender process may not have enough time to reach the call to send and so your handler.Available is 0 and the receive returns.
This is also why the "bug" does not occur when you add the sleep of 500 ms.