I have a socat TCP listener running on Linux (SLES 12). Any client that connects will pass a string to the socket and socat will execute a script which does some work with based on the string. The script echos some output which is passed back to client.
socat TCP-LISTEN:9996,fork EXEC:/home/abhishek/hello.sh
Below is the hello.sh script.
#!/bin/bash
read str
echo "[Hello] $str" | tee -a test.txt
When I run ncat client this works as expected. ncat is able to get the data back and output it.
echo abhishek | ncat 192.168.1.12 9996
[Hello] abhishek
Now I want to connect to socat through a .NET client written in C#. Below is the raw socket based code I have come up with.
IPAddress address = IPAddress.Parse("192.168.1.12");
IPEndPoint ipe = new IPEndPoint(address, 9996);
Socket client = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
client.Connect(ipe);
byte[] msg = Encoding.ASCII.GetBytes("abhishek");
// Send the data through the socket.
int bytesSent = client.Send(msg);
Console.WriteLine("Sent {0} bytes.", bytesSent);
byte[] bytes = new byte[128];
int bytesRec = client.Receive(bytes); ;
Console.WriteLine("Response text = {0}", Encoding.ASCII.GetString(bytes, 0, bytesRec));
client.Shutdown(SocketShutdown.Both);
client.Close();
I get the line "Sent 8 bytes" but after that client hangs on Receive. The client data is received by hello.sh becaused test.txt contains new entry. When I kill the client (Ctrl+C) socat prints
2018/02/03 10:12:03 socat[21656] E write(4, 0xe530f0, 17): Broken pipe
How should I read the reply from socat in C#?
Thanks
I was able to use TcpClient to establish communication with socat and get the output from script. Below is the main part of code I implemented.
TcpClient client = new TcpClient("192.168.1.12", 9999);
NetworkStream stream = client.GetStream();
StreamWriter writer = new StreamWriter(stream) { AutoFlush = true };
StreamReader reader = new StreamReader(stream);
//Send message to socat.
writer.WriteLine(message);
//Receive reply from socat.
string reply = reader.ReadLine();
stream.close();
client.close();
Related
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?
I have a robotic system that can be interacted with over TCP/IP. I have been able to control the system in Matlab using the following code:
AT = tcpip('cim-up',8000);
fopen(AT);
fprintf(AT, '$global[1] = 33');
I need to emulate the same command in C#. I have tried the following code:
// Connect to Robot using TCPIP
string IP = "cim-up";
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
try
{
tcpclnt.Connect(IP, 8000);
Console.WriteLine("Connected");
}
catch
{
Console.WriteLine("Failed");
}
StreamWriter AT_writer = new StreamWriter(tcpclnt.GetStream(), Encoding.ASCII);
AT_writer.Write("$global[1]=33");
This code will connect to the TCP/IP address but the server does not respond to the $global[1]=33 command.
I have also tried the following:
Byte[] data = System.Text.Encoding.ASCII.GetBytes("$global[1]=33");
// Get a client stream for reading and writing.
NetworkStream stream = tcpclnt.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
Does anyone have any suggestions as I have a successful Matlab implementation?
Thanks
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
i plan to write a Java TCP Server and a Client in C# .NET.
I take Java for the Server because i have the ability to run the Server on Linux.
My Problem is that the .NET Client can Connect to the Server but if i send something to the Server, the Server doesn´t receive anything.
Here is my Client:
static void Main(string[] args)
{
try
{
System.Net.Sockets.TcpClient tcpclnt = new System.Net.Sockets.TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("192.168.178.26", 1337);
Console.WriteLine("Connected");
Console.Write("Enter the string to be transmitted : ");
String str = Console.ReadLine();
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
Console.WriteLine("Transmitting.....");
stm.Write(ba, 0, ba.Length);
stm.Flush();
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(bb[i]));
tcpclnt.Close();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
And here is my Server:
public static void main(String argv[]) throws Exception
{
String clientSentence;
String capitalizedSentence;
ServerSocket socket = new ServerSocket(1337);
while(true)
{
System.out.println("... Server gestartet");
Socket connectionSocket = socket.accept();
BufferedReader inputFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
System.out.println(connectionSocket.getRemoteSocketAddress());
DataOutputStream outputStream = new DataOutputStream(connectionSocket.getOutputStream());
clientSentence = inputFromClient.readLine();
System.out.println("Received: " + clientSentence);
capitalizedSentence = clientSentence.toUpperCase() + "\n";
outputStream.writeBytes(capitalizedSentence);
}
}
The code i tested is only a Prototyp for Testing the connection to the Java Server.
I also plan to communicate with the Java Tcp Server with iOS and maybe Windows Phone.
So i hope anyone of you have an answer for me.
Your client sends the bytes of a line, and waits for a response, keeping the stream open.
Your server waits for a line break (or the end of the stream, i.e. the connection being closed) before ReadLine returns. So both sides are waiting for the other.
I would suggest that you use an OutputStreamWriter wrapped around the stream on the client side - then you can use WriteLine very simply (rather than messing around with the encoding yourself). When the server sees the line break, it will respond. I'd also use an InputStreamReader on the client rather than calling Convert.ToChar on each byte. Fundamentally, if you're only interested in transferring text and you're happy to use "a line" as the unit of messaging, using a writer/reader pair on both sides is the simplest approach.
When u know why the sent string "kamote" to server and the string received "kamote" from server are not the same..
CLIENT
tcpClient = new TcpClient();
tcpClient.Connect(ServerIP, Port);
connectionState = (HandShake("kamote", tcpClient)) ? "Connected to " + ServerIP.ToString() : "Host unreachable.";
private bool HandShake(String str, TcpClient tcpClient)
{
using (NetworkStream ns = tcpClient.GetStream())
{
byte[] toServer = Encoding.ASCII.GetBytes(str);
ns.Write(toServer,0,toServer.Length);
ns.Flush();
byte[] fromServer = new byte[10025];
ns.Read(fromServer, 0, (int)tcpClient.ReceiveBufferSize);
return Encoding.ASCII.GetString(fromServer).Equals(str);
}
}
SERVER
TcpClient tcpClient = new TcpClient();
tcpClient = tcpListener.AcceptTcpClient();
NetworkStream ns = tcpClient.GetStream();
byte[] fromClient = new byte[10025];
ns.Read(fromClient, 0, (int)tcpClient.ReceiveBufferSize);
byte[] toClient = fromClient;
ns.Write(toClient, 0, toClient.Length);
ns.Flush();
Client sent "kamote"
Server received "kamote"
Server sent "kamote"
Client received "kamote"
HandShake() always returns false. How can I fix this?
As in the previous question you asked, you're not keeping track of the number of bytes you received. So what's happening is this:
On the client, you send the string "kamote".
On the server, it receives that string into a buffer that's 10025 bytes long.
The server then sends the entire buffer back to the client -- all 10025 bytes
The client receives all or part of those 10025 bytes and converts them to a string.
The string that gets converted is really "kamote" with a bunch of 0's after it.
You must use the return value from Read to know how many bytes you received.
Did you try limiting the string length to the actual read bytes like this:
noOfBytes = ns.Read(bytes, 0, ...);
Encoding.ASCII.GetString(bytes, 0, noOfBytes);
You are including a lot of 0 characters, since you are including the entire fromServer in getstring. 0s don't print, but they are there. You must tell it the correct number of bytes to decode.