Connection method from client gets stuck upon reading response from server - c#

I have a client and a server app.
The server starts and upon starting, it waits for a connection as usual.
The client sends its request through a Custom Class I have called SocketMessage, SocketMessage simply stores the client's username and a string containing the method the client wants to request to the server.
The server gets the SocketMessage, deserealizes it and reads the string indicating the method, from this, it chooses a method to execute based on a switch statement.
I can send a request from the client, receive it at the server and send a response, but back at the client, when trying to read the response, the client's Connect method gets locked at streamReader.ReadLine
This is the SERVER, ClientCommunication is running on a subprocess.
private void ClientCommunication(object cliente)
{
TcpClient tcCliente = (TcpClient)cliente;
StreamReader reader = new StreamReader(tcCliente.GetStream());
StreamWriter serverStreamWriter = new StreamWriter(tcCliente.GetStream());
while (serverOn)
{
try
{
var msj= reader.ReadLine();
SocketMessage<object> msjReceived= JsonConvert.DeserializeObject<SocketMessage<object>>(msj);
SelectMethod(msjReceived.Method, msj, ref serverStreamWriter);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
}
tcCliente.Close();
}
public void SelectMethod(string pMethod, string pMsj, ref StreamWriter serverStreamWriter)
{
switch (pMethod)
{
case "CONNECT":
SocketMessage<string> connectMsj = JsonConvert.DeserializeObject<SocketMessage<string>>(pMsj);
LogConnection(connectMsj.Entidad);
serverStreamWriter.Write("CONNECTED");
serverStreamWriter.Flush();
break;
default:
break;
}
}
And this is the custom class for Client, which handles the sending of requests.
public string RequestConnection(string pUsername)
{
try
{
ipServer = IPAddress.Parse("127.0.0.1");
client = new TcpClient();
serverEndPoint = new IPEndPoint(ipServer, 16830);
client.Connect(serverEndPoint);
string serverRsp;
SocketMessage<string> connectionRequest= new MensajeSocket<string> { Method= "CONNECT", Entity = pUsername};
clientStreamReader = new StreamReader(cliente.GetStream());
clientStreamWriter = new StreamWriter(cliente.GetStream());
clientStreamWriter.WriteLine(JsonConvert.SerializeObject(connectionRequest));
clientStreamWriter.Flush();
Console.WriteLine("request SENT");
//THIS is where it gets stuck
serverRsp = clientStreamReader.ReadLine();
Console.WriteLine("streamReader READ " + serverRsp);
return serverRsp;
}
catch (SocketException ex)
{
Console.WriteLine(ex.Message);
return ex.Message;
}
}
Why is it getting stuck upon hitting serverRsp = clientStreamReader.ReadLine();? I know that ReadLine gets locked out until a response is received, but I'm sending the response from the server. I have confirmed that the server does receives the request and correctly logs it, but it seems the client is not able to read the related "CONNECTED" message, any idea what is going on?

ReadLine() waits for a line feed within the payload to terminate on. Where as your client is only sending a Write(), WriteLine() will append the line feed to the end of the payload thus the sever / listener knows when to stop listening for the data.
serverStreamWriter.Write("CONNECTED");

Related

C# SocketException (0x80004005) on every two attempt

My program creates a new TCP Socket, sends a request to a server and reads the response. If the response is requested, the program sends an acknowledge and if not it sends a negative acknowledge. This send and receive part work as intended.
The problem is that when i call the method a second time it throws SocketException (0x80004005). The third attempt works just as intended but every two attempt to send request to socket will fail.
public void Send(byte[] request)
{
var buffer = new byte[1024];
var received = 0;
try
{
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
socket.Connect(Address, Port);
socket.ReceiveTimeout = 5000;
socket.Send(request);
while ((received = socket.Receive(buffer)) > 0)
{
var response = buffer.Take(received);
if (IsRequested(response))
{
socket.Send(ACK);
var text = Encoding.UTF8.GetString(response);
Console.WriteLine(text);
return;
}
}
socket.Send(NAK);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
I have tried disconnecting, closing, disposing and every possible combination of the three without success.
I discovered that if I throw an exception right after sending the acknowledge, the method will work every time!
if (IsRequested(response))
{
socket.Send(ACK);
var text = Encoding.UTF8.GetString(response);
Console.WriteLine(text);
throw new Exception("Deliberate exception");
}
My question:
Why do I get SocketException (0x80004005) every two attempt if I don't throw an exception?

Can you read and write with a single Named Pipe client?

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.

Delay when send string via socket

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.

C# sockets server unable to receive data from same client connection more than once

I had recently asked a related question In C# how do I have a socket continue to stay open and accept new data? and somewhat solved it, but now I'm having trouble getting my server to receive data from the same client more than once.
I have written a simple socket server using a windows form in VS that has a button that calls a receive function
public void Receive()
{
try
{
byte[] bytes = new byte[256];
received = s1.Accept().Receive(bytes);
receivedText.Text += System.Text.ASCIIEncoding.ASCII.GetString(bytes);
}
catch (SocketException e)
{
Console.WriteLine("{0} Error code: {1}.", e.Message, e.ErrorCode);
return;
}
}
It works if the first time I send from my client, but if I try sending anything else and click on receive, my server just loops and never picks up the new data. However, if I send from somewhere else, or restart the connection from my client, I'm able to send data.
I would like to have my server able to receive any amount of data from the same client(s) at a time. Please ask if you need more code/details. Not sure what's relevant as I'm pretty new to socket programming.
You must call Accept() only once per client, not every time you want to receive new data. Accept() basically waits for a client to connect to your server socket, s1 (and returns a new socket to send/receive data with this client), so here each time your Receive() function is called your socket waits for another client to connect, that's why it works only once.
Here is an example (the code comes from your previous question) :
s1.Bind(endP);
s1.Listen(10);
Socket s2 = s1.Accept(); // Waits for a client to connect and return a socket, s2, to communicate with him
while (true) {
Receive(s2);
}
...
Receive() function :
public void Receive(Socket s)
{
try
{
byte[] bytes = new byte[256];
received = s.Receive(bytes);
receivedText.Text += System.Text.ASCIIEncoding.ASCII.GetString(bytes);
}
catch (SocketException e)
{
Console.WriteLine("{0} Error code: {1}.", e.Message, e.ErrorCode);
return;
}
}

Cannot get string data to pass through NamedPipeServerStream and NamedPipeClientStream

I'm trying to achieve bi-directional, named pipe communication on my Win-XP workstation using two simple C# forms solutions. One for the client and one for the server. They appear almost identical and use NamedPipeServerStream and NamedPipeClientStream (.NET 3.5). Both client and server are set to bidirectional comms via PipeDirection.InOut
The order of start-up events is:
1) Start the server. It waits for a connection from the client.
2) Start the client and it immediately finds and connects to the server. The server, likewise, completes its connection to the client.
3) Both client and server launch their "Read" threads which in turn create instances of streamreader. These threads then call ReadLn() and block - waiting for data. In all instances, autoflush is true.
I then use streamwriter.WriteLn() to send string data from the server to the client (or vice-versa). However, the execution never returns from that call. I don't know why and any insights would be greatfully received.
I have spent considerable time studying all that there is on this subject but I'm still missing something.
Client and server code snippets are shown:
SERVER:
private void ListenForClients()
{
// Only one server as this will be a 1-1 connection
m_pipeServerStream = new NamedPipeServerStream(PipeName, PipeDirection.InOut, 1);
// Wait for a client to connect
m_pipeServerStream.WaitForConnection();
// Ccould not create handle - server probably not running
if (!m_pipeServerStream.IsConnected)
return;
// Create a stream writer which flushes after every write
m_pipeServerWriter = new StreamWriter(m_pipeServerStream);
m_pipeServerWriter.AutoFlush = true;
Connected = true;
// Start listening for messages
if (m_pipeServerStream.CanRead)
{
ReadThread = new Thread(new ParameterizedThreadStart(Read));
ReadThread.Start(m_pipeServerStream);
}
}
/// <summary>
/// Reads data from the client
/// </summary>
/// <param name="serverObj"></param>
private void Read(object serverObj)
{
NamedPipeServerStream pipeStream = (NamedPipeServerStream)serverObj;
using (StreamReader sr = new StreamReader(pipeStream))
{
while (true)
{
string buffer;
try
{
buffer = sr.ReadLine();
}
catch
{
//read error has occurred
break;
}
//client has disconnected
if (buffer.Length == 0)
break;
//fire message received event
if (MessageReceived != null)
{
MessageReceived(buffer);
}
}
}
}
/// <summary>
/// Sends a message to the connected client
/// </summary>
/// <param name="message">the message to send</param>
public void SendMessage(string message)
{
if (m_pipeServerWriter != null)
{
m_pipeServerWriter.WriteLine(message);
m_pipeServerWriter.Flush();
}
}
CLIENT:
private void ConnectToServer()
{
// Seek out the one server
m_pipeClientStream = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut);
// Connect to the waiting server
m_pipeClientStream.Connect();
// Ccould not create handle - server probably not running
if (!m_pipeClientStream.IsConnected)
return;
// Create a stream writer which flushes after every write
m_pipeClientWriter = new StreamWriter(m_pipeClientStream);
m_pipeClientWriter.AutoFlush = true;
Connected = true;
// Start listening for messages
if (m_pipeClientStream.CanRead)
{
ReadThread = new Thread(new ParameterizedThreadStart(Read));
ReadThread.Start(m_pipeClientStream);
}
}
/// <summary>
/// Reads data from the server
/// </summary>
private void Read(object serverObj)
{
NamedPipeClientStream pipeStream = (NamedPipeClientStream)serverObj;
using (StreamReader sr = new StreamReader(pipeStream))
{
while (true)
{
string buffer;
try
{
buffer = sr.ReadLine();
}
catch
{
//read error has occurred
break;
}
//client has disconnected
if (buffer.Length == 0)
break;
//fire message received event
if (MessageReceived != null)
{
MessageReceived(buffer);
}
}
}
}
/// <summary>
/// Sends a message to the connected server
/// </summary>
/// <param name="message"></param>
public void SendMessage(string message)
{
if (m_pipeClientWriter != null)
{
m_pipeClientWriter.WriteLine(message);
m_pipeClientWriter.Flush();
}
}
Try setting the Async flag on the streams:
NamedPipeClientStream(".", PipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
I've now given up and moved to the safe, obvious technique of using two pipes, one for each direction of communication. They work fine.
I am not sure if this will help but I am also experiencing the same problem. First of all, I don't know why any reference to m_pipeServerStream.IsConnected will break the pipe. I tested this with just a simple MessageBox.Show(m_pipeServerStream.IsConnected.ToString()) and that broke my pipe!
Secondly, another weird thing is that your streamreader call will never return if you are using a duplex named pipe. You will need to read it manually like this
const int BufferSize = 4096;
Decoder decoder = Encoding.UTF8.GetDecoder();
StringBuilder msg = new StringBuilder();
char[] chars = new char[BufferSize];
byte[] bytes = new byte[BufferSize];
int numBytes = 0;
MessageBox.Show("before do while loop");
numBytes = pipeServer.Read(bytes, 0, BufferSize);
if (numBytes > 0)
{
int numChars = decoder.GetCharCount(bytes, 0, numBytes);
decoder.GetChars(bytes, 0, numBytes, chars, 0, false);
msg.Append(chars, 0, numChars);
}
MessageBox.Show(numBytes.ToString() + " " + msg.ToString());
MessageBox.Show("Finished reading, now starting writing");
using (StreamWriter swr = new StreamWriter(pipeServer))
{
MessageBox.Show("Sending ok back");
swr.WriteLine("OK");
pipeServer.WaitForPipeDrain();
}
Anyway, it doesn't seem to like the behavior of StreamReader, but this will work for now... I got this off this link http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/23dc2951-8b59-48e4-89fe-d2b435db48c6/
I'm not following every single step because I just needed to find out why it keeps hanging at StreamReader.ReadLine(). it's not returning from this function. StreamWriter does not seem to have this problem.
I am actually communicating between native dll and a managed windows service. Imagine my surprise when I found out that it was the managed part that was the problem, not the unmanaged part since they has such good examples in msdn...
I am no expert on Named Pipes or Anonymous Pipes but I will give it my best shot at trying to help others out even though you have a work around to your problem.
Client Server Communications is the best way to think of how this process should be achieved.
Server Starts and Listens for a Connection --> Client initiates a connection to a Server -->Server accepts the connection -->Client makes a request -->Server makes a response --> Connection is closed.
Server Starts and Listens for a Connection:
try
{
namedPipeServerStream = new NamedPipeServerStream(PipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
// Wait for a connection here...
namedPipeServerStream.BeginWaitForConnection(new AsyncCallback(ConnectionCallBack), namedPipeServerStream);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
Client Connects, then makes a Request:
try
{
namedPipeClientStream = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
// Connect with timeout...
namedPipeClientStream.Connect(TimeOut);
byte[] buffer = Encoding.UTF8.GetBytes(DataToSend);
namedPipeClientStream.BeginWrite(buffer, 0, buffer.Length, ConnectionCallBack, namedPipeClientStream);
}
catch (TimeoutException ex)
{
Debug.WriteLine(ex.Message);
}
ConnectionCallBack is an Asynchronous CallBack. This Method (this is on the Client) is where the Connection is managed:
private void ConnectionCallBack(IAsyncResult iAsyncResult)
{
try
{
// Get the pipe
NamedPipeClientStream namedPipeClientStream = (NamedPipeClientStream)iAsyncResult.AsyncState;
// End the write
namedPipeClientStream.EndWrite(iAsyncResult);
namedPipeClientStream.Flush();
// Get Server Response...
GetServerResponse(namedPipeClientStream);
// Flush Data and Close Pipe...
namedPipeClientStream.Flush();
namedPipeClientStream.Close();
namedPipeClientStream.Dispose();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
The Server handles the Client Request and formulates a Response and sends it:
// Response Methods...
public void SendResponse(string ServerResponse)
{
try
{
// Fill Buffer with Server Response Data...
byte[] Buffer = Encoding.UTF8.GetBytes(ServerResponse);
// Begin Async Write to the Pipe...
namedPipeServerStream.BeginWrite(Buffer, 0, Buffer.Length, SendResponseCallBack, namedPipeServerStream);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
private void SendResponseCallBack(IAsyncResult iAsyncResult)
{
try
{
// Get the Pipe Handle...
NamedPipeServerStream namedPipeServerStream = (NamedPipeServerStream)iAsyncResult.AsyncState;
// End the Write and Flush...
namedPipeServerStream.EndWrite(iAsyncResult);
namedPipeServerStream.Flush();
// Close the Connection and Dispose...
namedPipeServerStream.Close();
namedPipeServerStream.Dispose();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
This is called from the Client Request Handler:
private void ClientRequestHandler(string clientRequest)
{
try
{
if (this.InvokeRequired)
{
this.Invoke(new InvokedDelegate(ClientRequestHandler), clientRequest);
}
else
{
ProcessClientRequest(clientRequest);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
private void ProcessClientRequest(string clientRequest)
{
// Display the Client Request...
richTextBox1.Text = clientRequest;
PipeServer.SendResponse("Server has received Client Request at: " + DateTime.Now);
}
The Client has initiated a Connection to the Server, at the point where the Asynchronous CallBack Method see's this:
// Get Server Response...
GetServerResponse(namedPipeClientStream);
The Connection is still open. The Client Request was made and the Pipe was Flushed and is ready for the Client to Read the Server Response mentioned above:
private void GetServerResponse(NamedPipeClientStream namedPipeClientStream)
{
byte[] buffer = new byte[255];
namedPipeClientStream.Read(buffer, 0, buffer.Length);
// Convert byte buffer to string
string ResponseData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
// Pass message back to calling form
ServerResponse.Invoke(ResponseData);
}
The Response is received and then the Connection is again Flushed and Closed ready for the Client to Initiate another Connection.
The code is a little more complex than just this but essentially this is how it works. While you have a connection initiated, use it. Once you close it, and then try to re-initialise it, you will need to wait for a period of time for it to dispose properly or you will get all sorts of semaphore errors and so on. Don't Smoke your connection when you don't need to!!!
Please see: Code Project - C# Async Named Pipes for an excellent example

Categories

Resources