I have a TCP/IP client program in a Windows service written in C#. As of now everything is working fine. But I have a query that supposes my connection to the machine goes down due to any reasons say machine is out of the network or something. How will my application detect that and also tries to connect or regain the connection again?
Here is the code that I am using in my Windows service:
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
protected override void OnStart(string[] args)
{
_thread = new Thread(DoWork);
_thread.Start();
System.Timers.Timer _timer = new System.Timers.Timer(60 * 1000); // every 60 seconds
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
_timer.Start(); // <- important
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (client.Connected)
{
//Do nothing
}
else {
//close the thread and again start.
try
{
using (StreamWriter streamWriter = File.AppendText(textfileSaveLocation))
{
streamWriter.WriteLine("Disconnected!!!!");
}
}
catch (Exception Ex)
{
Ex.Message.ToString();
}
_shutdownEvent.Set();
_thread.Start();
}
}
private void DoWork()
{
while (!_shutdownEvent.WaitOne(0))
{
TcpClient client = new TcpClient();
string data= "";
fileSaveLocation = location;
try
{
client.Connect(new IPEndPoint(IPAddress.Parse(ip), port));
}
catch (Exception ex)
{
// Log the error here.
client.Close();
continue;
}
try
{
using (NetworkStream stream = client.GetStream())
{
byte[] notify = Encoding.ASCII.GetBytes("Hello");
stream.Write(notify, 0, notify.Length);
byte[] data = new byte[1024];
while (!_shutdownEvent.WaitOne(0))
{
int numBytesRead = stream.Read(data, 0, data.Length);
if (numBytesRead > 0)
{
data= Encoding.ASCII.GetString(data, 0, numBytesRead);
}
}
}
}
catch (Exception ex)
{
// Log the error here.
client.Close();
}
}
}
protected override void OnStop()
{
_shutdownEvent.Set(); // trigger the thread to stop
_thread.Join(); // wait for thread to stop
}
Please help me. Any suggestions will be helpful. Thanks ..
TcpClient does not get notified when the connection is closed or disconnected. You can check manually if TcpClient is connected in every certain period like -
if(tcpClient.Connected)
{
//code
}
else
{
//renew connection
}
Or, you have to handle the Exception in Catch block and code as required.
Related
I'm working on one TCP client server application and running the TCP server in loop but when I close the application loop continuously runs and send data to device.
Here is the scenario:
TCP server runs and listen to client(handheld device) once the device connected as long as there is no data receive from the device server needs to send empty data continuously to device.
Code:
private TCPMainListener tcpListener;
private Thread listenThread;
private TcpClient client;
public bool checkFormIsClose { get; set; }
List<Thread> listenThreads;
public void startTcpServer()
{
this.tcpListener = new TCPMainListener(IPAddress.Any, Convert.ToInt32(tcpport));
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
listenThreads.Add(listenThread);
}
private void ListenForClients()
{
try
{
this.tcpListener.Start();
}
catch (Exception ex)
{
throw ex;
}
while (!checkFormIsClose)
{
try
{
//blocks until a client has connected to the server
client = (TcpClient)this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
catch
{
break;
}
}
}
Client Handle:
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[100];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 40);
#region Write to client until message receive
int timeout = 0;
//send empty byte to device until bytesRead != 0
do
{
Thread.Sleep(50);
timeout++;
if (timeout == 10)
{
byte[] b = new byte[] { 0x00 };
tcpClient.GetStream().Write(b, 0, b.Length);
timeout = 1;
}
} while (bytesRead == 0);
#endregion
if (bytesRead != 0)
{
//message has successfully been received
if (BitConverter.ToString(message).Replace("-", "").StartsWith("FF"))
{
CardProcessing(message);
}
}
}
catch
{
//a socket error has occured
break;
}
}
tcpClient.Close();
}
Now here is my form closing code:
and they are not doing anything at all
private void TCPMAINSERVER_FormClosing(object sender, FormClosingEventArgs e)
{
foreach (Thread thread in listenThreads)
{
checkFormIsClose = true;
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
checkFormIsClose = true;
tcpListener.Stop();
Process.GetCurrentProcess().Close();
GC.SuppressFinalize(thread);
thread.Join();
thread.Interrupt();
});
}
}
private void TCPMAINSERVER_FormClosed(object sender, FormClosedEventArgs e)
{
foreach (Thread thread in listenThreads)
{
checkFormIsClose = false;
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
tcpListener.Stop();
Process.GetCurrentProcess().Close();
GC.SuppressFinalize(thread);
thread.Join();
thread.Interrupt();
});
}
}
first: I hope my english is not so bad (maybe it's gerglish; german grammer with english vocabularies)
I'm writing an server in java for android which communicates with an client written in c# running on WindowsCE 5. The big problem is that sometimes especially or maybe only if the network is unstable my java server still blocks in the accept-Method also when the client is sending data. I simulated the unstable network by switch off and on my virtual router over which both devices communicate. I also could recognize that the c#-program hangs in the write- or read-method or throws an IOException also when the network is switched on and my server is hearing on the expected port.
Here is the source code of the client:
Some information:
1. It is sending 10000 messages only for testing
static void Main(string[] args)
{
string server = ...;
int port = 12000;
String outputStr = "";
NetworkStream stream = null;
for (int i = 0; i < 10000; i++)
{
TcpClient client = null;
String messageToSend = ...
try
{
IPAddress ipAddress = IPAddress.Parse(server);
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port);
AutoResetEvent connectDone = new AutoResetEvent(false);
client = new TcpClient();
client.Client.BeginConnect(ipEndPoint,
new AsyncCallback(
delegate(IAsyncResult ar)
{
try
{
client.Client.EndConnect(ar);
connectDone.Set();
}
catch (Exception ex)
{}
}
), client.Client);
if (!connectDone.WaitOne(5000, false))
{
outputStr = "NOTConnected";
}
Byte[] data = System.Text.Encoding.UTF8.GetBytes(messageToSend);
stream = client.GetStream();
try
{
stream.Write(data, 0, data.Length);
data = new Byte[2048];
int bytes = stream.Read(data, 0, data.Length);
string responseData = System.Text.Encoding.UTF8.GetString(data, 0, bytes);
outputStr = responseData;
}
catch (IOException ex)
{
outputStr = ex.Message;
}
}
}
catch (SocketException ex)
{
outputStr = ex.Message;
}
catch (Exception ex)
{
outputStr = ex.Message;
}
finally
{
if (stream != null) stream.Close();
}
System.Threading.Thread.Sleep(200);
}
Console.WriteLine("\n Press Enter to continue... " + outputStr);
Console.Read();
}
And my source code of the server:
Some information. My servlet normally is an inner class and first checks if the devices is connected to a router. If it is it starting to here on a port. If not it goes to wait mode (see _sendToSleep()). If devices is reconnected the activity can wakes it up by notify. If it looses again the connection the Activity will cause a SocketException by closing the socket so the servlet can leave the accept-method.
public class ServletThread extends Thread {
private int port;
private ServerSocket serverSocket;
private Socket socket;
public ServletThread(int port) throws IOException {
super();
this.port = port;
serverSocket = new ServerSocket(port);
}
private void checkConnectivity(BufferedWriter out) {
try {
String outgoingMsg = "connected";
out.write(outgoingMsg);
out.flush();
} catch (IOException e) {
Log.e(TAG, "connectivity exception " + e.getMessage());
}
}
private void readStream(Scanner scanner) throws IOException {
String str = "";
while (scanner.hasNext()) {
str += scanner.nextLine();
}
final String fTicket = str;
runOnUiThread(new Runnable() {
#Override
public void run() {
if (MyActivity.this.isFinishing()) {
return;
}
// do something
}
});
}
private void _sendToSleep() {
try {
synchronized (this) {
this.wait();
}
} catch (InterruptedException e) {
this.interrupt();
}
}
#Override
public void interrupt() {
super.interrupt();
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
Log.e(TAG, ""+e.getMessage());
}
}
}
#Override
public void run() {
try {
serverSocket = new ServerSocket(port);
} catch (IOException ex) {
Log.e(TAG,""+ex.getMessage());
}
while (!isInterrupted()) {
if (connectionState != NetworkInfo.State.CONNECTED) {
_sendToSleep();
} else {
BufferedWriter out = null;
Scanner scanner = null;
try {
socket = serverSocket.accept();
out = new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream()));
scanner = new Scanner(socket.getInputStream());
checkConnectivity(out);
readStream(scanner);
} catch (IOException ex) {
Log.e(TAG, ex.getMessage() + "");
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
Log.e(TAG, "exception on close socket " + e.getMessage());
}
}
if (scanner != null) {
scanner.close();
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
Log.e(TAG, ""+e.getMessage());
}
}
}
}
}
}
}
After isolating the bug, i did some changes:
c# instead of stream = client.getStream
(using Stream = client.getStream()) {
...
stream.WriteTimeout = 1000;
stream.ReadTimeout = 1000;
...
}
in java changes in the _sendToSleep()
private void _sendToSleep() {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
Log.e(TAG, "failed to close serverSocket " + e.getMessage());
}
}
try {
synchronized (this) {
this.wait();
}
} catch (InterruptedException e) {
this.interrupt();
}
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
Log.e(TAG, "failed to open serversocket " + e.getMessage());
}
}
It became better, means, I could not reproduce the problem.
My questions:
Why did it the client hang? (maybe a synchronisation problem on servlet-side and client between socketserver and wlan-adapter after reconnecting several times, so that the servlet cannot get any data???)
And do my changes solve the problem.
Thanking you in anticipation!
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!
I'm writing a tcp server in c# and corresponding client in java. I'm testing the connection on localhost, and the client is able to connect to the server. However, when I'm sending messages, the client never receives them. Using the debugger I've verified that stream.Write(...) is executed. Any idea what the problem could be?
This is the c# server:
TcpClient client = (TcpClient)cl;
NetworkStream stream = client.GetStream();
byte[] msg = new byte[512];
int bytesRead;
while (running)
{
while (messages.getCount() > 0)
{
String msg = messages.Take();
if (cmd != null)
{
byte[] bytes = Encoding.UTF8.GetBytes(msg.ToCharArray());
try
{
stream.Write(bytes, 0, bytes.Length);
stream.Flush();
}
catch (Exception e)
{
}
}
}
Thread.Sleep(1000);
}
And the Java client:
public void run()
{
try
{
socket = new Socket(address, port);
in = new BufferedReader( new InputStreamReader( socket.getInputStream() ));
out = new PrintWriter(socket.getOutputStream());
running = true;
}
catch (Exception e){
e.printStackTrace();
running = false;
}
String data;
while(running)
{
try
{
data = in.readLine();
if(data != null)
{
processData(data);
}
}
catch (IOException e)
{
e.printStackTrace();
running = false;
break;
}
}
try
{
socket.close();
socket = null;
}
catch (IOException e)
{
e.printStackTrace();
}
running = false;
}
You're using BufferedReader.readLine(). Are your message strings terminated by a CR, LF, or CR/LF?
readLine blocks until a line-terminating character is read.
I have an update server that sends client updates through TCP port 12000. The sending of a single file is successful only the first time, but after that I get an error message on the server "Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host". If I restart the update service on the server, it works again only one time. I have normal multithreaded windows service.
SERVER CODE
namespace WSTSAU
{
public partial class ApplicationUpdater : ServiceBase
{
private Logger logger = LogManager.GetCurrentClassLogger();
private int _listeningPort;
private int _ApplicationReceivingPort;
private string _setupFilename;
private string _startupPath;
public ApplicationUpdater()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
init();
logger.Info("after init");
Thread ListnerThread = new Thread(new ThreadStart(StartListener));
ListnerThread.IsBackground = true;
ListnerThread.Start();
logger.Info("after thread start");
}
private void init()
{
_listeningPort = Convert.ToInt16(ConfigurationSettings.AppSettings["ListeningPort"]);
_setupFilename = ConfigurationSettings.AppSettings["SetupFilename"];
_startupPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Substring(6);
}
private void StartListener()
{
try
{
logger.Info("Listening Started");
ThreadPool.SetMinThreads(50, 50);
TcpListener listener = new TcpListener(_listeningPort);
listener.Start();
while (true)
{
TcpClient c = listener.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(ProcessReceivedMessage, c);
}
}
catch (Exception ex)
{
logger.Error(ex.Message);
}
}
void ProcessReceivedMessage(object c)
{
try
{
TcpClient tcpClient = c as TcpClient;
NetworkStream Networkstream = tcpClient.GetStream();
byte[] _data = new byte[1024];
int _bytesRead = 0;
_bytesRead = Networkstream.Read(_data, 0, _data.Length);
MessageContainer messageContainer = new MessageContainer();
messageContainer = SerializationManager.XmlFormatterByteArrayToObject(_data, messageContainer) as MessageContainer;
switch (messageContainer.messageType)
{
case MessageType.ApplicationUpdateMessage:
ApplicationUpdateMessage appUpdateMessage = new ApplicationUpdateMessage();
appUpdateMessage = SerializationManager.XmlFormatterByteArrayToObject(messageContainer.messageContnet, appUpdateMessage) as ApplicationUpdateMessage;
Func<ApplicationUpdateMessage, bool> HandleUpdateRequestMethod = HandleUpdateRequest;
IAsyncResult cookie = HandleUpdateRequestMethod.BeginInvoke(appUpdateMessage, null, null);
bool WorkerThread = HandleUpdateRequestMethod.EndInvoke(cookie);
break;
}
}
catch (Exception ex)
{
logger.Error(ex.Message);
}
}
private bool HandleUpdateRequest(ApplicationUpdateMessage appUpdateMessage)
{
try
{
TcpClient tcpClient = new TcpClient();
NetworkStream networkStream;
FileStream fileStream = null;
tcpClient.Connect(appUpdateMessage.receiverIpAddress, appUpdateMessage.receiverPortNumber);
networkStream = tcpClient.GetStream();
fileStream = new FileStream(_startupPath + "\\" + _setupFilename, FileMode.Open, FileAccess.Read);
FileInfo fi = new FileInfo(_startupPath + "\\" + _setupFilename);
BinaryReader binFile = new BinaryReader(fileStream);
FileUpdateMessage fileUpdateMessage = new FileUpdateMessage();
fileUpdateMessage.fileName = fi.Name;
fileUpdateMessage.fileSize = fi.Length;
MessageContainer messageContainer = new MessageContainer();
messageContainer.messageType = MessageType.FileProperties;
messageContainer.messageContnet = SerializationManager.XmlFormatterObjectToByteArray(fileUpdateMessage);
byte[] messageByte = SerializationManager.XmlFormatterObjectToByteArray(messageContainer);
networkStream.Write(messageByte, 0, messageByte.Length);
int bytesSize = 0;
byte[] downBuffer = new byte[2048];
while ((bytesSize = fileStream.Read(downBuffer, 0, downBuffer.Length)) > 0)
{
networkStream.Write(downBuffer, 0, bytesSize);
}
fileStream.Close();
tcpClient.Close();
networkStream.Close();
return true;
}
catch (Exception ex)
{
logger.Info(ex.Message);
return false;
}
finally
{
}
}
protected override void OnStop()
{
}
}
I have to note something that my windows service (server) is multithreaded.
On the receiving end, set up a while loop to listen until there's no more data, then exit gracefully: close the stream and client. The framework TCP libs consider it an issue to drop a connection cold on thread exit and will therefore throw the exception you're seeing.
This will also save you from an intermittent problem you'll likely see once you correct the current one: Stream.Read with a length specifier won't always give you your full buffer each time. It looks like you're sending (up to) 2kb chunks and receiving into a (single-shot) 1kb buffer anyhow so you may start to get XML exceptions as well.
If that's not enough detail, ask and I'll dig up some old TcpClient code.