Client/server architecture - c#

I am developing an application for ticketing, client checks for a trip and sends via networkstream to the server, then it will return to the client if that trip was found or not, ex: if trip was not found, it shows in the client trip not found, but then if I choose another trip location, and click again on the checktrip button, the client stops working.
Here below, code of check trip in the client:
try
{
NetworkStream ns = client.GetStream();
StreamWriter sw = new StreamWriter(ns);
StreamReader sr = new StreamReader(ns);
sw.WriteLine(comboBox1.Text);
sw.WriteLine(comboBox2.Text);
sw.WriteLine(dateTimePicker1.Text);
sw.WriteLine(dateTimePicker2.Text);
sw.Flush();
ns.Flush();
string x = sr.ReadLine();//freeze point trying abother reservation.
//MessageBox.Show("Value of x = "+x);
if (x.Equals("yes"))
{
MessageBox.Show("Trip Found");
proceedBtn.Enabled = true;
}
else
{
MessageBox.Show("Trip Not Found\nPlease Try another");
}
}

Do you close your streams? What exact error do you encounter?
//your try block ends here...
catch(Exception ex){MessageBox.Show(ex.Message);}
finally
{
sr.Close(); sw.Close(); ns.Close();
}
EDIT: If you close your streams, you should re-create your TcpClient object and Connect again. Or if you don't want to do this, don't close the streams, the connection should be kept alive

Related

How to correctly use network stream to get data?

I have an app communicates with industry machines through TCP/IP protocol.
It should come out something after I send an command to the machine's end point.
However, though I have implemented it with the way that Microsoft document shows,
my app never reads the data from the network stream.
Here is the code:
//The tcp client has been connected here.
if (client.Connected)
{
var stream = client.GetStream();
if (stream.CanWrite)
{
var bytes = Encoding.ASCII.GetBytes("010000000004");
stream.Write(bytes, 0, bytes.Length);
stream.Flush();
}
while(stream.DataAvailable is false) //keep sleeping when the data is not available
{
Thread.Sleep(10);
}//The loop will be endless
if (stream.CanRead) //I can't get to this step
{
var reader = new StreamReader(stream, Encoding.ASCII);
var result = reader.ReadLine();
}
}
I want to get the message from the machine so that I can interact with it.

How can I send multiple string messages from client to server using a single instance of TcpClient?

I have separate client and server console apps. I'm simply trying to send a string from the client to the server and have the server write the string to the console using TcpClient. I can send a single message just fine but when I throw a while loop into the client app to try and send multiple messages without closing the TcpClient, the server doesn't write anything to the console.
//Server
using (TcpClient client = listener.AcceptTcpClient())
{
NetworkStream ns = client.GetStream();
byte[] buffer = new byte[1024];
while (true)
{
if (ns.DataAvailable)
{
int bytesRead = 0;
string dataReceived = "";
do
{
bytesRead = ns.Read(buffer, 0, buffer.Length);
dataReceived += Encoding.UTF8.GetString(buffer, 0, bytesRead);
}
while (bytesRead > 0);
Console.WriteLine($"Message:{ dataReceived }\n");
}
}
}
//Client
using (TcpClient client = new TcpClient(hostname, port))
{
if (client.Connected)
{
Console.WriteLine("Connected to server");
NetworkStream ns = client.GetStream();
string message = "";
//Removing this while loop I can send a single message that the server will write to console
//but with the loop present the server does not write anything
while (true)
{
message = Console.ReadLine();
byte[] messageBytes = UTF8Encoding.UTF8.GetBytes(message);
ns.Write(messageBytes);
Console.WriteLine($"Message Sent! ({ messageBytes.Length } bytes)");
}
}
}
I'm interested in learning sockets and have been pouring over SO questions and MSDN docs for two days but cannot figure out why it's not working as I intend. I feel a bit silly even submitting a question because I'm sure it's something basic I'm not understanding. Could someone please drop some knowledge on me?
SOLUTION
//Server
using (TcpClient client = listener.AcceptTcpClient())
{
NetworkStream ns = client.GetStream();
StreamReader sr = new StreamReader(ns);
string message = "";
while (true)
{
message = sr.ReadLine();
Console.WriteLine(message);
}
}
//Client
using (TcpClient client = new TcpClient(hostname, port))
{
if (client.Connected)
{
Console.WriteLine("Connected to server");
NetworkStream ns = client.GetStream();
StreamWriter sw = new StreamWriter(ns) {Autoflush = true};
string message = "";
while (true)
{
message = Console.ReadLine();
sw.WriteLine(message);
}
}
}
If you debug your server, you'll see that it does receive data. You're just not displaying the data, because the only output your server does is after the loop when the byte count returned is 0: Console.WriteLine($"Message:{ dataReceived }\n");. The byte count will only be 0 when the underlying socket has been shutdown. That never happens because your client is stuck in an infinite loop.
A better approach, for a simple text-based client/server example like this, is to use StreamWriter and StreamReader with line-based messages, i.e. WriteLine() and ReadLine(). Then the line breaks serve as the message delimited, and your server can write the message each time it receives a new line.
Note also that in your example above, you are assuming that each chunk of data contains only complete characters. But you're using UTF8 where characters can be two or more bytes, and TCP doesn't guarantee how bytes that are sent are grouped. Using StreamWriter and StreamReader will fix this bug too, but if you wanted to do it explicitly yourself, you can use the Decoder class, which will buffer partial characters.
For some examples of how to correctly implement a simple client/server network program like that, see posts like these:
.NET Simple chat server example
C# multithreading chat server, handle disconnect
C# TcpClient: Send serialized objects using separators?

Reading and writing on and from named pipe

I'm trying out IPC with named pipes in a test application that I wrote for that purpose. I want to read a value from a pipe, but the reader doesn't seem to read anything.
I'm starting a server process and a client. The server uses a named pipe called InitPipe to tell the client a name for a new pipe for communication. After that happens, a new server process and the client get connected to the new pipe, the other server process and client get disconnected and the InitPipe reopened for new processes to communicate with the server.
The client writes data to the pipe and the new server process should read the data. That's where the problem is. The server doesn't seem to get the values off the pipe.
private void svr_task(string comPipe)
{
var server = new NamedPipeServerStream(comPipe);
write("Com-Pipe: " + comPipe); //'write' just writes to a TextBox on the UI thread
server.WaitForConnection();
write("Client connected: " + comPipe);
StreamReader reader = new StreamReader(server);
StreamWriter writer = new StreamWriter(server);
while (server.IsConnected)
{
var line = reader.ReadLine(); //the program doesn't seem to run past this line
write(line);
}
write("Client disconnected: " + comPipe);
server.Dispose();
write("Com-Pipe closed: " + comPipe);
}
private void cl_start()
{
//This is for InitPipe
var clientInit = new NamedPipeClientStream("InitPipe");
NamedPipeClientStream client = new NamedPipeClientStream("InitPipe");
clientInit.Connect();
Dispatcher.Invoke(() => stat_cl1.Content = "Initialize...");
StreamReader reader = new StreamReader(clientInit);
StreamWriter writer = new StreamWriter(clientInit);
while (clientInit.IsConnected)
{
var line = reader.ReadLine();
client = new NamedPipeClientStream(line);
clientInit.Dispose();
}
//This is where the communication with the server thread starts
client.Connect();
Dispatcher.Invoke(() => stat_cl1.Content = "Connected");
reader = new StreamReader(client);
writer = new StreamWriter(client);
while (client.IsConnected)
{
string line = Dispatcher.Invoke(() => box_cl1.Text); //read a value from a textbox (This works)
writer.Write(line);
writer.Flush();
}
client.Dispose();
Dispatcher.Invoke(() => stat_cl1.Content = "Not connected");
}
I want the server thread to receive the values from the client thread. The UI thread is not locked so that I can start another client, which can also connect to a server thread.
When debugging in VS and stepping through the code, it just runs after var line = reader.ReadLine(); and seems to never get to the next line. So that's why I think it can't read any values from the pipe. But what do I need to change? I want to output the value with write.
I ran into a similar problem. It has to do with how namedpipes work. You can either be writing to or reading from a named pipe at a time. try not attaching StreamReader and StreamWriter to the stream at the same time. I got around this by a reader stream and a writer stream separate. Also, you can use the same pipe name for multiple clients, you just have to create a new instance of server after a client connects.

disconnecting a client from server after receiving message in c# socket

I have made a small client program which will receive a message from server. I want to disconnect the client from the server safely after receiving the message.(Another case may also arise such that, I want to compare the received value with another value and if the don't match, the client will be disconnected) My sample code is:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
class Program
{
static void Main(string[] args)
{
try
{
TcpClient tcpClient = new TcpClient("127.0.0.1", 1234);
NetworkStream ns = tcpClient.GetStream();
StreamReader sr = new StreamReader(ns);
StreamWriter sw = new StreamWriter(ns);
string data;
//receiving message
data = sr.ReadLine();
Console.WriteLine(data);
//I want to disconnect here
}
catch (Exception e)
{
Console.Write(e.Message);
}
Console.Read();
}
}
What additional things will I need to add?
Just wrap the usage of the TcpClient instance and NetworkStream in a using block:
using(TcpClient tcpClient = new TcpClient("127.0.0.1", 1234))
using(NetworkStream ns = tcpClient.GetStream())
{
// Do read here
}
I would structure your code more like:
using (var tcpClient = new TcpClient("127.0.0.1", 1234))
{
using(var ns = tcpClient.GetStream())
{
StreamReader sr = new StreamReader(ns);
StreamWriter sw = new StreamWriter(ns);
string data;
//receiving message
data = sr.ReadLine();
if(data == somePreDeterminedValue)
{
Console.WriteLine(data);
}
}
}
This will mean that when you hit the closing brace it'll automatically close the TCPClient and NetworkStream for you and dispose of their instances.
In this case if the value you get from the stream is correct then it won't disconnect, simple. I think you'll need to provide what you want to do overall for a complete answer to your question as in this simple terms that is what I'd do, but in this example the TCPClient is closed regardless.
In a real world application you'd essentially want to keep a field of the TCPClient that you open and close throughout the application and only dispose of when your messaging object is disposed.

c# tcpclient program writing to stream but client not receiving data

I have written a TCPClient program to run on my PC. It first initiates a TCP listener to listen on a specific port then reads/writes from/to multiple TCP clients on multiple threads.
I am able to read from the client but whenever I try to send data to it, the program displays that it has sent the data, but the client does not receive anything.
Here's the code:
TcpClient client = listener.AcceptTcpClient();
var childSocketThread = new Thread(() =>
{
if (client.Connected)
{
using (NetworkStream stream = client.GetStream())
{
Console.WriteLine("connected");
byte[] data = new byte[1000];
try
{
if (stream.CanRead)
{
stream.Read(data, 0, 1000);
string dataStr = Encoding.ASCII.GetString(data);
string dataa = dataStr.TrimEnd('\0');
//Console.WriteLine(dataa);
if (dataa.Length > 10)
{
deviceid = ParseRequest(dataa);
byte[] sendnow = Encoding.ASCII.GetBytes(reply[deviceid]);
Array.Clear(data, 0, 1000);
Console.WriteLine("Recieved data: " + dataa);
Console.WriteLine("Sending data");
using (StreamWriter writer = new StreamWriter(stream))
{
writer.AutoFlush = true;
writer.WriteLine(reply[deviceid]);
}
Console.WriteLine(reply[deviceid]);
Console.WriteLine("Sent");
}
Console.WriteLine();
}
}
catch (Exception es)
{
Console.WriteLine(es);
}
}
}
});
childSocketThread.Start();
The server device that I am using is a PLC. Also, things I have already tried:
1) sending directly using Socket.Send method.
2) sending directly using NetworkStream method.
3) accepting the TCP connection as sockets. (Socket device = listener.AcceptSocket).
None of these methods seem to send to the device, even though the program tells me that it had no issues sending data since it displays "Sent" after attempting to send data.
I downloaded another program from this link http://www.codeproject.com/Articles/488668/Csharp-TCP-Server. The test app they provide with it is able to send and receive data on the same port as my program running on the same PC.
I haven't been able to get any direction on how to diagnose and more importantly solve this issue. Any ideas?
Update 2015-08-10 11:18 a.m.:
Output of the Program is as follows:
Update 2015-08-10 11:32 a.m.:
Output of Syslog Console:
Update 2015-08-10 12:07 p.m.:
Output of Wireshark:
We need you to post both sides code. Nevertheless, here is some code that works just fine, you can use it to see if you are doing something wrong.
http://www.codeproject.com/Articles/1415/Introduction-to-TCP-client-server-in-C

Categories

Resources