I make an application in android can send character code to server C# when user input on android keyboard.
This is send method in android side:
public Boolean writeMessage(String message) {
try {
printWriter = new PrintWriter(socket.getOutputStream(), true);
printWriter.println(message);
return true;
} catch (Exception ex) {
Log.e(TAG,"write error: " +ex.getMessage());
return false;
}
}
And server listen the messages (C#):
Thread myThread = new Thread(new ThreadStart(ServeClient));
myThread.Start();
void ServeClient(){
StreamReader reader = new StreamReader(tcpClient.GetStream());
while (true)
{
try
{
String message = reader.ReadLine();
if (message != null)
{
Console.WriteLine(message);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
My code works, but when user input faster, the server delay read message in 1,2 or 3 seconds (I have test the method get character when user input, it works fine, not delay). Where is my problem? Thanks in advance!
Your problem may be caused by Nagle's algorithm reducing TCP traffic. Consider setting TCP_NODELAY on your client (and server - TcpClient.Client.NoDelay - if communication is two-way).
Edit: For java it is Socket.setTcpNoDelay method.
Related
I'm using UdpClient to receive data from a single host(actually it's a microcontroller that sends 32 bytes of data every 4 milliseconds.
The program I wrote is pretty simple.
I'm initializing the UdpClient like this(in Program.cs):
public static UdpClient client = new UdpClient(1414);
after that i do this in Form_Load event:
static UdpClient client = Program.client;
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
and then call the client.Recieve() like this:
Task.Run(() =>
{
while (true)
{
try
{
data = client.Receive(ref RemoteIpEndPoint);
}
catch (Exception ex)
{
String err_type = ex.GetType().Name;
if (err_type == "SocketException")
{
MessageBox.Show("Cannot Find The Device.", "Device Error.");
}
}
}
});
the program runs fine on my own system (using Windows 10). However when i run this program on windows 7,at random times,but with 100% chance client.Recieve() stops working and the program no longer receives any data. no exception is thrown. to find the root of the problem, I installed Wireshark to test if there is any incoming data.The answer was no(the LAN port light stops blinking too) . What has me confused is that this does not happen on windows 10.
The thing is, you miss all exceptions except SocketException.
To find out, what's going on, please, rewrite your catch block:
Task.Run(() =>
{
while (true)
{
try
{
data = client.Receive(ref RemoteIpEndPoint);
}
catch (SocketException ex)
{
MessageBox.Show("Cannot Find The Device.", "Device Error.");
}
catch (Exception e)
{
MessageBox.Show(e.GetType().Name, e.Message);
}
}
});
Turns out my code was completely fine.
This was a hardware problem on our side.
I have a standalone test application developed in c# (4.5).
The application is primarily meant for sending some data to COM ports. The application accepts the data through the UI and the corresponding data is sent to respective COM ports.
For eg: Data from text box 1 goes to COM 1 on pressing a button, Data from Textbox 2 goes to COM 2 on pressing a different button etc.
Later I had to add a functionailty where a different set of data has to be accepted via Windows sockets and has to be sent to a different COM port other than above. This listening socket could receive data from multiple sources. If the listening socket receives back to back socket data, the application is expected to queue the data and process the data on a First come first serve bases.
Hence I created a synchronous socket to receive data. If the server receives data from 2 sources, it processes the data from source 1 and sends the completion status to source 1 and then takes the data from source 2,processes it and informs the status and this goes on. The socket is created on a thread so that it could receive and process data independently from the UI.
The application was meeting its objective as most of the communication was through sockets and people were not really using the UI for entering data.
Recently, as people started UI, i noticed a completely new issue. When someone tries to enters a data on to UI while the socket data is in process, it stops the socket data processing. When I press ctrl+Alt+Del on the host, it resumes the processing of the socket data.
I could not identify my mistake here. Also, I looked over to the Backgroundworkder class but I am not sure if that would allow the sockets commands to be processed in a synchronous way.
Please treat me as a newbie as I am still learning and complex suggestions might be hard to digest.
public partial class frm_bot : Form
{
public frm_bot()
{
StartServer();
}
private void frm_bot_Load(object sender, EventArgs e)
{
try
{
myThread = new System.Threading.Thread(new System.Threading.ThreadStart(OnClientConnect));
myThread.IsBackground = true;
myThread.Start();
}
catch (Exception ex)
{
showErrorMsg(ex.Message);
}//catch
}
public void StartServer()
{
InitializeComponent();
System.Net.IPAddress localIPAddress = System.Net.IPAddress.Parse(GetlocalIp());
IPEndPoint ipLocal = new IPEndPoint(localIPAddress, 8089);
_listener = new TcpListener(ipLocal);
}
private void OnClientConnect()
{
try
{
_listener.Start();
TcpClient clientSocket = default(TcpClient);
clientSocket = _listener.AcceptTcpClient();
_clientSocket = clientSocket;
ReadCallback();
}
catch (Exception se)
{
MessageBox.Show("Could not bind to Port 8089! Please close all Applications that uses Port 8089");
}
}
public void ReadCallback()
{
try
{
using (StreamReader sr = new StreamReader(_clientSocket.GetStream()))
using (StreamWriter sw = new StreamWriter(_clientSocket.GetStream()))
{
sw.AutoFlush = true;
char[] c = null;
while (sr.Peek() >= 0)
{
c = new char[25];
sr.Read(c, 0, c.Length);
Console.WriteLine(c);
}
string d = new string(c);
string[] cmddata = d.Split('\0');
string dataFromClient = cmddata[0];
if (dataFromClient.Length == 0)
{
Console.WriteLine("Client sent empty string!");
}
else
{
ProcessSocketData(dataFromClient);
sw.Write("Done");
}
sw.Close();
}
OnClientConnect();
}
catch (Exception ex)
{
OnClientConnect();
return;
}
}
public void ProcessSocketData(string sockdata)
{
try
{
// Socket data is processed here.
}
catch (Exception ex)
{
MessageBox.Show("Exception on ProcessSocketData: " + ex.Message);
return;
}
}
}
I have installed a Windows Service for my project, this error pop out when I start the service.
error 1503 the service didn't respond to the start or control request in a timely fashion
However, this project works fine when I debug in Visual Studio Code but when I use Visual Studio 2017 to create and start the service by following this tutorial and
Few solution I tried but the error still the same. Here are the solution I have tried.
Use CCCleaner to scan and fix issues
Modify ServicesPipeTimeout to 180000
The Logservice below can write the String into a text file, where I analyze the service run up until which part then fails. The service only able to run until LogService("3"); then it fails at receive the bytes from port.
Here is the code:
public Service1()
{
InitializeComponent();
LogService("server");
try
{
LogService("1");
IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
UdpClient udpListener = new UdpClient(514);
byte[] bReceive; string sReceive; string sourceIP;
Console.WriteLine("Waiting...");
/* Main Loop */
/* Listen for incoming data on udp port 514 (default for SysLog events) */
while (true)
{
LogService("2");
try
{
LogService("3");
bReceive = udpListener.Receive(ref anyIP);
LogService("4");
/* Convert incoming data from bytes to ASCII */
sReceive = Encoding.ASCII.GetString(bReceive);
LogService(sReceive);
/* Get the IP of the device sending the syslog */
sourceIP = anyIP.Address.ToString();
LogService("5");
LogService(sourceIP);
new Thread(new logHandler(sourceIP, sReceive).handleLog).Start();
/* Start a new thread to handle received syslog event */
LogService(sReceive);
}
catch (Exception ex) { Console.WriteLine(ex.ToString()); }
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
throw ex;
}
}
I'm not sure if the error is occur because of the codes or other reasons
Update
Refer to this post, I tried to turn off the firewall to receive all the connection, but the error still remain the same.
There was once my project successfully listen the data from the server after I add udpListener.Client.Bind(anyIP); into the code, but then after some modification it is not functioning again. I'm not sure is the Bind() make the code works even just for once.
This is the way I solve my error refer to this post. Anyway, I'm not completely understand the process behind this, if anyone have some good example or link in explaining this solution please don't hesitate to comment below.
protected override void OnStart(string[] args)
{
LogService("Service started");
NewThread = new Thread(runSysLog);
NewThread.Start();
}
protected override void OnStop()
{
LogService("Service stopped");
StopRequest.Set();
//NewThread.Join();
}
public void runSysLog()
{
try
{
AutoResetEvent StopRequest = new AutoResetEvent(false);
/* Main Loop */
while (true)
{
if (StopRequest.WaitOne(5000)) return;
try
{
//while (udpListener.Available > 0)
if (udpListener.Available > 0)
{
//Some code here
}
}
catch (Exception ex)
{
LogService("Whileloop exception: " +ex.ToString());
throw ex;
}
}
}
catch (Exception ex)
{
LogService("Run Sys Log Exception: " +ex.ToString());
throw ex;
}
}
I have some problem with receiving frames in C#. After few hours from application start, some frames are lost.
Well, at start I'm running two threads which are receiving data. Code:
public void ATSListenerThreadA(MainWindow mainWindow)
{
UdpClient listenerA = new UdpClient(19001);
listenerA.Client.ReceiveBufferSize = 1000;
IPEndPoint remoteIPEndPointA = new IPEndPoint(IPAddress.Any, 1);
Byte[] receivedBytes;
try
{
while (mainWindow.ATSThreadActive)
{
receivedBytes = listenerA.Receive(ref remoteIPEndPointA);
if (receivedBytes.Length > 170)
{
Log.Write(MessageType.Info, "BUG KANAL A: " + BitConverter.ToString(receivedBytes));
}
mainWindow.ATSTimeoutTimer.Start();
ATSDataReceived(Channel.A, mainWindow, receivedBytes);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public void ATSListenerThreadB(MainWindow mainWindow)
{
UdpClient listenerB = new UdpClient(19002);
listenerB.Client.ReceiveBufferSize = 1000;
IPEndPoint remoteIPEndPointB = new IPEndPoint(IPAddress.Any, 1);
Byte[] receivedBytes;
try
{
while (mainWindow.ATSThreadActive)
{
receivedBytes = listenerB.Receive(ref remoteIPEndPointB);
if (receivedBytes.Length > 170)
{
Log.Write(MessageType.Info, "BUG KANAL B: " + BitConverter.ToString(receivedBytes));
}
mainWindow.ATSTimeoutTimer.Start();
ATSDataReceived(Channel.B, mainWindow, receivedBytes);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ATSDataReceived(Channel channel, MainWindow mainWindow, Byte[] received)
{
try
{
mainWindow.Dispatcher.Invoke(() =>
{
mainWindow.ATSStatusLabel.Foreground = System.Windows.Media.Brushes.Green;
mainWindow.ATSStatusLabel.Content = "OK";
});
ATSInterface.UpdateObjects(channel, received);
}
catch (Exception ex)
{
mainWindow.Dispatcher.Invoke(() =>
{
mainWindow.ATSStatusLabel.Foreground = System.Windows.Media.Brushes.Red;
mainWindow.ATSStatusLabel.Content = "ERR";
});
Log.Write(MessageType.Warning, ex.Message);
}
lock (this)
{
if (mainWindow.ATSTimeoutTimer != null)
{
mainWindow.ATSTimeoutTimer.Stop();
mainWindow.ATSTimeoutTimer.Start();
}
}
}
Then, in ATSDataReceived method, received data are processed with calling method ATSInterface.UpdateObjects(). Of course inside ATSInterface.UpdateObjects() method is lock. I was trying to receiving data synchronously and asynchronously, but it doesn't change anything. Also I was checking if two frames are not sticking together, but it's not this too. As I said, problem araises after few hours from program start, in both threads simultaneously.
I might add that frames are coming very often, once at ~150 ms.
What can be a reason?
some frames are lost.
That's perfectly normal for UDP. By design, you may or may not ever receive a datagram that was sent to you.
Other unreliable behaviors of UDP include the possibility that a given datagram may be received more than once, and that one datagram may be received after a different datagram that was sent later than it (i.e. the datagrams are not guaranteed to be received in the same order in which they were sent).
If you want reliable communications, you will need to use TCP, or add reliability features on top of your UDP protocol.
udp is unreliable protocol to use.
if you want to make sure that everything arrives you need to use TcpClient instead.
I've written a little apllication that creates a named pipe server and a client that connects to it. You can send data to the server, and the server reads it successfully.
The next thing I need to do is receive messages from the server, so I've got another thread that spawns and sits and waits for incoming data.
The problem is that whilst the thread is sat waiting for incoming data, you can no longer send messages to the server as it hangs on the WriteLine call as I assume the pipe is now tied up checking for data.
So is it just that I'm not approaching this properly? Or are named pipes not meant to be used like this? The examples I've seen on named pipes seem to only go one way, a client sends and a server receives, although you can specify the direction of a pipe as In, Out or both.
Any help, pointers or suggestions would be appreciated!
Heres' the code so far:
// Variable declarations
NamedPipeClientStream pipeClient;
StreamWriter swClient;
Thread messageReadThread;
bool listeningStopRequested = false;
// Client connect
public void Connect(string pipeName, string serverName = ".")
{
if (pipeClient == null)
{
pipeClient = new NamedPipeClientStream(serverName, pipeName, PipeDirection.InOut);
pipeClient.Connect();
swClient = new StreamWriter(pipeClient);
swClient.AutoFlush = true;
}
StartServerThread();
}
// Client send message
public void SendMessage(string msg)
{
if (swClient != null && pipeClient != null && pipeClient.IsConnected)
{
swClient.WriteLine(msg);
BeginListening();
}
}
// Client wait for incoming data
public void StartServerThread()
{
listeningStopRequested = false;
messageReadThread = new Thread(new ThreadStart(BeginListening));
messageReadThread.IsBackground = true;
messageReadThread.Start();
}
public void BeginListening()
{
string currentAction = "waiting for incoming messages";
try
{
using (StreamReader sr = new StreamReader(pipeClient))
{
while (!listeningStopRequested && pipeClient.IsConnected)
{
string line;
while ((line = sr.ReadLine()) != null)
{
RaiseNewMessageEvent(line);
LogInfo("Message received: {0}", line);
}
}
}
LogInfo("Client disconnected");
RaiseDisconnectedEvent("Manual disconnection");
}
// Catch the IOException that is raised if the pipe is
// broken or disconnected.
catch (IOException e)
{
string error = "Connection terminated unexpectedly: " + e.Message;
LogError(currentAction, error);
RaiseDisconnectedEvent(error);
}
}
You cannot read from one thread and write on another thread to the same pipe object. So while you could create a protocol where the listening position changes depending on the data you're sending, you cannot do both at the same time. You will need a client and server pipe on both sides to do this.