I am working on my project where I want to make local P2P communication in C# using Sockets and Threads. I am faced with some troubles when I run my code.
I think the problem is inside next while loop
while (true)
{
try
{
TcpListener listener = new TcpListener(IPAddress.Parse(STD_IP), HOST_PORT);
listener.Start();
using (TcpClient client = listener.AcceptTcpClient())
using (NetworkStream nwStream = client.GetStream())
{
Thread listenerThread = new Thread(() =>
{
string message = Receive(nwStream);
updateBoard(message);
});
listenerThread.Start();
string response = stanje;
Send(nwStream, response);
}
}
catch (Exception er)
{
MessageBox.Show("Communication error: \n\n" + er.Message + "\n" + er.StackTrace);
}
}
while (true) is an infinite loop that your posted code has no way of escaping from.
Related
My connection handler is below (this is more for personal experimentation than production code)
If I don't add a Thread.Sleep anywhere in the while loop, it starts sucking down CPU.. Conversely, if I do Sleep to alleviate the endless while-spam, I miss the disconnection.. The CPU goes up in direct proportion to the number of clients/threads running, so it's not the listener itself that's causing the high usage, it's the actual client thread posted below.. Anyone have any ideas on how to solve this?
(I'm avoiding await-based solutions as I'm not familiar enough with async/await and the threaded method is working fine for this rather small project)
I only briefly searched around SO looking for a solution and didn't notice any that were this specific problem or that provided a solution other than directing folks to async/await articles, so sorry if I did miss an applicable answer.
private void HandleConnection(CancellationToken ct) {
int recv = 0;
byte[] buf = new byte[4096];
Trace.WriteLine($"{_name} Connected");
if (_ns.CanWrite && _client.Connected) {
_ns.Write(Encoding.BigEndianUnicode.GetBytes("■WEL"), 0, Encoding.BigEndianUnicode.GetBytes("■WEL").Length);
try {
while (_client.Connected && !ct.IsCancellationRequested) {
while (!_ns.DataAvailable) { //first attempted solution
Thread.Sleep(100); // miss discon if i sleep here
}
if (ct.IsCancellationRequested) {
Trace.WriteLine($"{(string)this} thread aborting");
break;
}
buf = new byte[4096];
if (_client.Connected && _ns.DataAvailable) {
recv = _ns.Read(buf, 0, buf.Length);
} else {
recv = 0;
}
if (recv > 0) {
string r = Encoding.BigEndianUnicode.GetString(buf);
r = r.TrimEnd('\0');
if (String.IsNullOrEmpty(r) || String.IsNullOrWhiteSpace(r))
r = null; //need the !not version
else
if (ParseMsg(r))
break;
}
//Thread.Sleep(100); // also miss discon here too
}
} catch (IOException ioe) { }
Trace.WriteLine($"{_name} Disconnected");
if (OnDisconnected != null)
OnDisconnected(this);
}
}
The proper way to communicate over a socket is:
Continuously read. These reads will block until data comes in or until the socket is gracefully disconnected (detectable by a read completing with 0 bytes read).
Periodically write. These writes are required to ensure the connection is still viable.
A proper threading approach requires two threads per connection. I'm not convinced that it's simpler than an asynchronous approach.
P.S. If your code uses Connected, then it has a bug. Proper solutions never need to use Connected.
I had the same problema than you but I found that the best way to solve this problem is:
Not Blocking the Socket with sleeps and thread.
UPGRADE: If you use threads and sleeps into your server, it will suffer a low performance to receive and answer each message by each connection.
If you want an High Performance App you must not use sleeps or create thread for each connection that you accept. The best way is using the Asyncronous methods that NetworkStream provides, using BeginRead and EndRead, for example:
public void run()
{
server = new TcpListener(IPAddress.Any, port);
server.Start();
log.Info("Starting SocketServer on Port [" + port + "]");
while (keepRunning)
{
try
{
TcpClient socket = server.AcceptTcpClient();
if (keepRunning)
RequestManager.createRequestForEvalue(socket, idLayout);
}
catch (Exception ex)
{
log.Error(ex.Message);
log.Error(ex.StackTrace);
}
}
log.Info("Server Stoped.");
}
public static bool createRequestForEvalue(TcpClient socket, int idLayout)
{
Request req = null;
req = new Request(socket,idLayout);
registerRequest(req.ID,req); //Registra el Request, para su posterior uso.
// DO NOT CREATE THREADS FOR ATTEND A NEW CONNECTION!!!
//Task.Factory.StartNew(req.RunForIVR);
//ThreadPool.QueueUserWorkItem(req.RunForIVR);
req.startReceiveAsync(); //Recive data in asyncronus way.
return true;
}
public void startReceiveAsync()
{
try
{
log.Info("[" + id + "] Starting to read the Request.");
requestBuffer = new byte[BUFFER_SIZE];
NetworkStream nst = socket.GetStream();
nst.BeginRead(requestBuffer, 0,BUFFER_SIZE, this.requestReceived, nst);
}catch(Exception ex)
{
log.Error("[" + id + "] There was a problem to read the Request: " + ex.Message);
RequestManager.removeRequest(id);
closeSocket();
}
}
public void requestReceived(IAsyncResult ar)
{
try
{
NetworkStream nst = socket.GetStream();
int bread = nst.EndRead(ar); //Block the socket until all the buffer has been available.
message = Encoding.UTF8.GetString(requestBuffer, 0, BUFFER_SIZE);
log.Info("[" + id + "] Request recived: [" + message +"]");
RunForIVR();
}
catch (Exception ex)
{
log.Error("[" + id + "] There was a problem to read the Request: " + ex.Message);
RequestManager.removeRequest(id);
closeSocket();
}
}
public void SendResponse(String Response)
{
StringBuilder sb = new StringBuilder();
sb.Append(Response);
sb.Append('\0', BUFFER_SIZE - Response.Length);
string message = sb.ToString();
log.Info("[" + id + "] ivrTrans CMD: [" + idCMD + "] RESPONSE: [" + Response + "]");
NetworkStream nst = socket.GetStream();
byte[] buffer = new byte[BUFFER_SIZE];
for (int i = 0; i < BUFFER_SIZE; i++)
buffer[i] = (byte)message.ElementAt(i);
nst.BeginWrite(buffer, 0, BUFFER_SIZE, this.closeSocket, nst);
}
public void closeSocket(IAsyncResult ar = null)
{
try
{
if (ar != null) //Since 4.24
{
NetworkStream nst = socket.GetStream();
nst.EndWrite(ar);
}
socket.Close();
socket = null;
}catch(Exception ex)
{
log.Warn("[" + id + "] There was a problem to close the socket. Error: " + ex.Message + Environment.NewLine + ex.StackTrace);
}
log.Info("[" + id + "] Socket closed.");
}
Upgrade I use the EndRead to be sure that the request has been arrived at all.
By Other way, you can use BeginWrite and EndWrite to know when the socket has been finished of write to close the connection
In this way you are attended the connection in a continues way and as soon as possible. In my case i reduce the CPU usage from 30% to 0%, for an a mount of 15K request per hour.
I want to send a message from a C# application to the Android emulator or device over TCP. I have searched on Google and got the maximum results for Android client and C# server but not what I want to acheive.
Here is what I have tried; maybe I am going about it the wrong way but what I want is to send a message over TCP to an Android device.
Server Code to send a message:
private static int port = 4444;
private static TcpListener listener;
private static Thread thread;
private static int clientId = 0;
listener = new TcpListener(new IPAddress(new byte[] { 127, 0, 0, 1 }), port);
thread = new Thread(new ThreadStart(Listen));
thread.Start();
private static void Listen()
{
listener.Start();
MessageBox.Show("Listening on: " + port.ToString());
while (true)
{
MessageBox.Show("Waiting for connection....");
MessageBox.Show("Client No: " + clientId);
TcpClient client = listener.AcceptTcpClient();
Thread listenThread = new Thread(new ParameterizedThreadStart(ListenThread));
listenThread.Start(client);
}
}
private static void ListenThread(Object client)
{
NetworkStream netstream = ((TcpClient)client).GetStream();
MessageBox.Show("Request made");
clientId = clientId + 1;
// String message = "Hello world";
byte[] resMessage = Encoding.ASCII.GetBytes(clientId.ToString());
netstream.Write(resMessage, 0, resMessage.Length);
netstream.Close();
}
Client Code
private TextView textDisplay;
Socket socket;
private static final int TCP_SERVER_PORT = 4444;
ServerSocket ss = null;
try {
ss = new ServerSocket(TCP_SERVER_PORT);
//ss.setSoTimeout(10000);
//accept connections
Socket s = ss.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//receive a message
String incomingMsg = in.readLine() + System.getProperty("line.separator");
Log.d("TcpServer", "received: " + incomingMsg);
textDisplay.append("received: " + incomingMsg);
//send a message
String outgoingMsg = "goodbye from port " + TCP_SERVER_PORT + System.getProperty("line.separator");
out.write(outgoingMsg);
out.flush();
Log.d("TcpServer", "sent: " + outgoingMsg);
textDisplay.append("sent: " + outgoingMsg);
//SystemClock.sleep(5000);
s.close();
} catch (InterruptedIOException e) {
//if timeout occurs
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
Log.d("Error",e.toString());
}
}
}
The problem lies in your Client code.
A socket is opened between two parties, one that plays the role of the listener / server that does bind->listen->accept and a client that connect
In your code there are two problems:
Your client should connect and not accept
Both your client and your server will try to read from the socket and write afterwards. There would be no problem if your read and write operations from the socket were on different threads.In your case this will result in a deadlock.
If you want both operations to be done on the same thread , sequentially then your client and server should perform the read and write in opposite order :
Client : read -> write
Server: write-> read
Sometimes, on some machines often and on some seldom, the clients which are using my program are getting a "pipe is being closed" exception. This happens on the NamedPipeServerStream that is on .WaitForConnection(). After that, the Application totally crashes and releases a windows exception. This happens when a NamedPipeClientStream transfers information to the standalone application.
main Funktionality:
I wrote several Tools (Office Toolbars, a Service, a standalone .net Application, and a litle starter exe) that communicate together with NamedPipes.
The Service runs a NamedPipeServerStream that is always open (in state .WaitForConnection();) and the Standalone Application has a NamedPipeServerStream too.
The Toolbars and starter .exe communicate with the service. The Service then with the Standalone Application.
what kind of problems can release the pipe is being closed Exception?
Is it possible that the server sends information to the Standalone Application but closes the stream to early because the Standalone Application is not ready or something? on each NamedPipeClientStream i do a waitforpipedrain if pipeClient.IsConnected befor i close the pipeclient..
thanks for help
edit: Here an Example of a clientstream
using (NamedPipeClientStream pipeClient =
new NamedPipeClientStream(".", pipename, PipeDirection.Out))
{
// Wait for a client to connect
try
{
pipeClient.Connect(3000);
// send params to the form
using (StreamWriter sw = new StreamWriter(pipeClient))
{
sw.AutoFlush = true;
sw.WriteLine(sendtext);
}
}
// Catch the IOException that is raised if the pipe is
// broken or disconnected.
catch (Exception e)
{
if (sid != "")
{
connections.Remove(conName);
}
eventLog1.WriteEntry("SendText Fehler 1 " + e.Message);
}
finally
{
if (pipeClient.IsConnected)
{
pipeClient.WaitForPipeDrain();
}
pipeClient.Close();
pipeClient.Dispose();
}
Example of an pipeserver (that runs in a seperad thread)
NamedPipeServerStream pipeServer;
PipeSecurity pipe_security = CreateSystemIoPipeSecurity();
do
string pipename = global::TOfficeCenter.Properties.Settings.Default.pipename;
string aText = "";
pipeServer = new NamedPipeServerStream(pipename, PipeDirection.In, ONE_INSTANCE, PipeTransmissionMode.Byte,
PipeOptions.None, IN_BUF_SIZE, OUT_BUF_SIZE, pipe_security);
try
{
// Verbindung zu TOfficeCenter.exe aufbauen
try
{
IsWaiting = true;
pipeServer.WaitForConnection();
IsWaiting = false;
using (StreamReader sr = new StreamReader(pipeServer))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
aText = aText + temp;
}
}
try
{
if (aText == "")
{
empfang(null);
}
else
{
if (aText != "KillPipe")
{ // XML empfangen
XmlDocumentTC xml = new XmlDocumentTC();
xml.LoadXml(aText);
empfang(xml);
}
}
}
catch (Exception)
{
empfang(null);
}
}
catch
{...........
}
}
catch (Exception e)
{...........
}
} while (running);
pipeServer.Close();
It's possible that i finally found the problem..
I found out that after this code:
using (StreamWriter sw = new StreamWriter(pipeClient))
{
sw.AutoFlush = true;
sw.WriteLine(sendtext);
}
the pipeClient.IsConnected(); returns directly false, so that it never comes to the WaitForPipeDrain. I Now did it like that and hope that the client does not close the connection before the server is finished with reading..
using (StreamWriter sw = new StreamWriter(pipeClient))
{
sw.AutoFlush = true;
sw.WriteLine(sendtext);
pipeClient.WaitForPipeDrain();
}
Do You Think that could have solved the problem? Since i did it, i never got the error on two test-machines. But the Errors anyway happened seldom..
My use is a bit different, but I'll include the server thread in sum as it's mostly being hacked from the MSDN page at present:
MSDN: How to Use Named Pipes
Not sure if the "WaitForPipeToDrain()" is needed for me, but I took it from your code :)
I think the reset of the pipeServer each time is what cleaned up my IOException.
int threadId = Thread.CurrentThread.ManagedThreadId;
bool sentinel = true;
while (sentinel)
{
NamedPipeServerStream pipeServer =
new NamedPipeServerStream("shapspipe", PipeDirection.InOut, 1);
// Wait for a client to connect
pipeServer.WaitForConnection();
Console.WriteLine("Client connected on thread[{0}].", threadId);
try
{
// Read the request from the client. Once the client has
// written to the pipe its security token will be available.
StreamString ss = new StreamString(pipeServer);
// Verify our identity to the connected client using a
// string that the client anticipates.
ss.WriteString("I am the one true server!");
string message = ss.ReadString();
Console.WriteLine("received from client: " + message);
ss.WriteString("echo from server: " + message);
Console.WriteLine("Received from client: {0} on thread[{1}] as user: {2}.",
message, threadId, pipeServer.GetImpersonationUserName());
}
// Catch the IOException that is raised if the pipe is broken
// or disconnected.
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
pipeServer.WaitForPipeDrain();
pipeServer.Close();
}
I'm writting a client(Android) - server(c#) application. I get the code from here:
How to make client on Android listen to server on C#?
Everythings is working fine, when i just send message from the client to server, and from server to client (closing the socket on server side). Now, what i want is : send message to server, receive message from server, then send again a message to server. The server hangs at sending the message. If i close the socket on server side after sending, it gives a dispose error, and i can's send the data from the server.
My server code is:
/*************************************SERVER*****************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace SERVER2
{
class Program
{
public static void Main()
{
try
{
IPAddress ipAd = IPAddress.Parse("192.168.2.102");
TcpListener myList = new TcpListener(ipAd, 18001);
myList.Start();
Console.WriteLine("The server is running at port 18001...");
Console.WriteLine("The local End point is :" +
myList.LocalEndpoint);
Console.WriteLine("Waiting for a connection.....");
m:
Socket s = myList.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
byte[] b = new byte[100];
int k = s.Receive(b);
char cc = ' ';
string test = null;
Console.WriteLine("Recieved1...");
for (int i = 0; i < k - 1; i++)
{
cc = Convert.ToChar(b[i]);
test += cc.ToString();
}
Console.WriteLine("Received characters1: "+test);
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("The string was recieved by the server."));
Console.WriteLine("\nSent Acknowledgement");
//s.Close(); <-if i enable this, i get a dispose error
k = s.Receive(b);//i get dispose error here
cc = ' ';
test = null;
Console.WriteLine("Recieved2...");
for (int i = 0; i < k - 1; i++)
{
cc = Convert.ToChar(b[i]);
test += cc.ToString();
}
Console.WriteLine("Received characters2: " + test);
/* clean up */
goto m;
s.Close();
myList.Stop();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.Message);
}
Console.ReadLine();
}
}
}
My client code is:
/******************************CLIENT*****************************************/
Socket socket = null;
try
{
Toast.makeText(context,"IP: "+ip+" port: "+port,10000).show();
InetAddress serverAddr = InetAddress.getByName(ip);
socket = new Socket(serverAddr, port);
}
catch (UnknownHostException e1)
{
Toast.makeText(context,"UnknownHostException ",10000).show();
}
catch (IOException e1)
{
Toast.makeText(context,"IOException ",10000).show();
}
String message = "1";
PrintWriter out = null;
BufferedReader in = null;
try {
Log.d("TCP", "C: Sending: '" + message + "'");
/*write*/
out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
out.println(message);
out.flush();
/*read*/
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String text = "";
String finalText = "";
while ((text = in.readLine()) != null)
{
finalText += text;
}
Toast.makeText(context, "FinalText: "+finalText, 10000).show();
Log.d("TCP", "C: Sent.");
Log.d("TCP", "C: Done.");
in.close();
/*write*/
out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
out.println(message);
out.flush();
} catch(Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Thanks advanced !!!
The reason you get the dispose error is because the s.close() closes the socket, and then your next s.Receive() is trying to read from a closed socket.
Also the hang you are seeing might be caused by in.close(); in your java code. It could be closing the underlying socket. Try commenting it out and see if that fixes your hanging problem.
Not an expert in C#, but I've done my share of socket programming.
Basically what you want is 1 + n threads.
One thread that just accepts connections.
For each socket that is returned by Socket s = myList.AcceptSocket(); you want a thread for sending/receiving data and processing the messages from the socket. You could also use two threads (one that sends, one that receives (this is the asynchronous case)).
You should use the stream of the tcp client.. an example can be found here: http://msdn.microsoft.com/de-de/library/system.net.sockets.tcplistener.aspx
And don't use goto, please.
You will never reach the end lines after goto m;
Surround the code with a while loop which checks if an timeout is occured or any other checks.
The reason why the server hangs is that he waits for 100 bytes to receive.
The problem was that when the client received the message from the server , in the while part entered into an infinite loop. I modify my app like this:
My client part:
try
{
Toast.makeText(context,"IP: "+ip+" port: "+port,10000).show();
InetAddress serverAddr = InetAddress.getByName(ip);
socket = new Socket(serverAddr, port);
}
catch (UnknownHostException e1)
{
Toast.makeText(context,"UnknownHostException ",10000).show();
}
catch (IOException e1)
{
Toast.makeText(context,"IOException ",10000).show();
}
String message = "HELLO FROM CLIENT";
PrintWriter out = null;
BufferedReader in = null;
try {
Log.d("TCP", "C: Sending: '" + message + "'");
/*write*/
OutputStream ostr=socket.getOutputStream();
OutputStreamWriter outputstr=new OutputStreamWriter(ostr);
BufferedWriter buffw=new BufferedWriter(outputstr);
out = new PrintWriter(buffw ,true);
out.println("HELLO 1 FROM CLIENT");
/*read - i modify to this*/
InputStreamReader reader=new InputStreamReader(socket.getInputStream());
char[] bytesreceived=new char[50];
reader.read(bytesreceived , 0, 50);
String text="";
for (int i=0;i<bytesreceived.length;i++)
{
text+=bytesreceived[i];
}
Toast.makeText(context, "Received1: "+text.trim(), 10000).show();
Log.d("IdealLog","Received1: "+text.trim());
/*write*/
out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
out.println("HELLO 2 FROM CLIENT");
/*read*/
reader=new InputStreamReader(socket.getInputStream());
bytesreceived=new char[50];
reader.read(bytesreceived , 0, 50);
text="";
for (int i=0;i<bytesreceived.length;i++)
{
text+=bytesreceived[i];
}
Toast.makeText(context, "Received2: "+text.trim(), 10000).show();
Log.d("IdealLog","Received2: "+text.trim());
} catch(Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
My server side code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace SocketServer
{
class Program
{
static void Main(string[] args)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, 18001);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(ip);
socket.Listen(10);
Console.WriteLine("Waiting for a client...");
Socket client = socket.Accept();
IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}", clientep.Address, clientep.Port);
string welcome = "HELLO 1 FROM SERVER";
byte[] data = new byte[200];
int receiveddata=client.Receive(data);
Console.WriteLine("Received data from CLIENT1: {0}", System.Text.ASCIIEncoding.ASCII.GetString(data).Trim());
ASCIIEncoding asen = new ASCIIEncoding();
byte[] data2 = new byte[200];
data2 = asen.GetBytes(welcome);
int sentdata=client.Send(data2, data2.Length, SocketFlags.None);
Console.WriteLine("Sent data from SERVER: {0}", welcome);
byte[] data3 = new byte[200];
Console.WriteLine("Receiving data from CLIENT : {0}", "...");
client.Receive(data3);
Console.WriteLine("Received data from CLIENT2: {0}", System.Text.ASCIIEncoding.ASCII.GetString(data3).Trim());
byte[] data4 = new byte[200];
data4 = asen.GetBytes("HELLO 2 FROM SERVER");
sentdata = client.Send(data4, data4.Length, SocketFlags.None);
client.Close();
socket.Close();
Console.WriteLine("Disconnected from {0}", clientep.Address);
Console.ReadLine();
}
}
}
Now, everything is working fine, without hang. The only problem is, that i don't know if this will work for receiving , sending files.
I've read a couple of posts on SignalR and thought for a fun test project that I could create a web application to poll my onkyo receiver for status and display the results in a browser. For an initial test, I was successfully able to send the current time on the server back to the client by using this code in Application_Start:
ThreadPool.QueueUserWorkItem(_ =>
{
dynamic clients = Hub.GetClients<KudzuHub>();
while (true)
{
clients.addMessage(DateTime.Now.ToString());
Thread.Sleep(1000);
}
});
In the client javascript, i have the following code:
// Proxy created on the fly
var kHub = $.connection.kudzuHub;
// Declare a function on the hub so that the server can invoke it
kHub.addMessage = function (message) {
console.log('message added');
$('#messages').append('<li>' + message + '</li>');
};
// start the connection
$.connection.hub.start();
So all of that works fine. Every second, I get a new list item containing the current server date and time.
Now when I add this code to read data from the Onkyo receiver, it breaks: (still in Application_Start)
ThreadPool.QueueUserWorkItem(_ =>
{
dynamic clients = Hub.GetClients<KudzuHub>();
try
{
while (true)
{
string host = ConfigurationManager.AppSettings["receiverIP"].ToString();
int port = Convert.ToInt32(ConfigurationManager.AppSettings["receiverPort"]);
TcpClient tcpClient = new TcpClient(host, port);
NetworkStream clientSockStream = tcpClient.GetStream();
byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
clientSockStream.Read(bytes, 0, (int)tcpClient.ReceiveBufferSize);
tcpClient.Close();
clients.addMessage(System.Text.Encoding.ASCII.GetString(bytes));
Thread.Sleep(50);
}
}
catch (SocketException ex)
{
// do something to handle the error
}
});
I set a break point and stepped through the code. It gets to this line and then returns.
clientSockStream.Read(bytes, 0, (int)tcpClient.ReceiveBufferSize);
It never finishes the rest of the code to send the message to the client. What am I doing wrong?
Thanks.
I would make some structural changes to your loop to allow the receiver time to respond, remove the overhead of retrieving the configuration every 50 milliseconds, and cleanup the open network stream:
ThreadPool.QueueUserWorkItem(_ =>
{
dynamic clients = Hub.GetClients<KudzuHub>();
TcpClient tcpClient = null;
NetworkStream clientSockStream = null;
try
{
string host = ConfigurationManager.AppSettings["receiverIP"].ToString();
int port = Convert.ToInt32(ConfigurationManager.AppSettings["receiverPort"]);
while (true)
{
if (tcpClient == null) {
tcpClient = new TcpClient(host, port);
clientSockStream = tcpClient.GetStream();
}
if (clientSockStream.CanRead) {
byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
try {
clientSockStream.Read(bytes, 0, (int)tcpClient.ReceiveBufferSize);
} catch (Exception ex) {
// Add some debug code here to examine the exception that is thrown
}
tcpClient.Close();
// Closing the client does not automatically close the stream
clientSockStream.Close();
tcpClient = null;
clientSockStream = null;
clients.addMessage(System.Text.Encoding.ASCII.GetString(bytes));
}
Thread.Sleep(50);
}
}
catch (SocketException ex)
{
// do something to handle the error
} finally {
if (tcpClient != null) {
tcpClient.Close();
clientSockStream.Close();
}
}
});