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.
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 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 am writing a C# client application which will connect to the server written in python. My question is about receiving data in loop. The application structure is all about client asks server -> server responds to client. Everything works fine when the message is lower that actual buffer size (set in server). For example: server side buffer: 1024, client buffer size: 256, data length < 1kb. I run my application with following code:
int datacounter = 0;
byte[] recived = new byte[256];
StringBuilder stb = new StringBuilder();
serverStream.ReadTimeout = 1500;
try
{
while ((datacounter = serverStream.Read(recived, 0, 256)) > 0)
{
Console.WriteLine("RECIVED: " + datacounter.ToString());
stb.append(System.Text.Encoding.UTF8.GetString(recived, 0, datacounter));
}
}
catch { Console.WriteLine("Timeout!"); }
Then the application receives data in 4 loops (256 bytes each):
RECIVED: 256
RECIVED: 256
RECIVED: 256
RECIVED: 96
And then the timeout ticks, that ends the transmission and pass the complete data to later analysis (from stb object). I don't think using timeout is proper, but i don't know any other way to do this.
However, this way it works. Here we go with example, that does not:
server side buffer: 1024, client side buffer: 256, data length ~ 8kbytes (python side sends data in loop).
RECIVED: 256
RECIVED: 256
RECIVED: 256
RECIVED: 256
Then the timeout ticks (and obviosly the data is incomplete - got 1kb of 8kb). Sometimes the loop even ends after 1 run with 28 recived bytes and thats all before timeout. Python says that the data has been send properly. Here's the way i create the socket and serverStream object:
TcpClient clientSocket = new TcpClient();
clientSocket.Connect("x.y.z.x", 1234);
NetworkStream serverStream = clientSocket.GetStream();
Its not the TcpClient fault. Tried the same with clear sockets, created like:
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
However that works similar. Is there a way, to make my loop work without timeout, receiving all data? I would like to keep the socket synchronous if possible.
I don't think there's anything wrong with your receive code functionally. I put together a test, and the receiver gets as much as you can send it (eg. 8 MBs), as long as you keep sending without 1.5 seconds pause, before timing out.
So it looks like your server is simply not sending "fast" enough.
To answer your question, timing is not the typical way of knowing when you have received a full message. One common, simple way of determining when a full message is received is to prefix the length of the full message on the sending side (eg. 4-byte int). Then on the receive side, first read 4 bytes, decode to the length, and then read that many more bytes.
You could also consider appending a message termination string, such as Environment.NewLine, to the end of your message. This has the advantage that you could call StreamReader.ReadLine(), which will block until the full message is received. This only works if the termination can NOT be included in the message itself.
If you can't alter the server protocol, is there any other way of knowing you have received a full message? (eg. checking for a NewLine at the end of the message, an XML end tag, or some other pattern.) If not, perhaps you could wait for the server to disconnect, otherwise it looks like you would be forced to find the right timing balance.
I am including the test code below in case you want to play around with it.
Server/Sending Side:
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
TcpListener server = new TcpListener(localAddr, 13579);
server.Start();
TcpClient clientSocket = server.AcceptTcpClient();
NetworkStream stream = clientSocket.GetStream();
int bytesSent = 0;
int bytesToSend = 1 << 25;
int bufferSize = 1024;
string testMessage = new string('X', bufferSize);
byte[] buffer = UTF8Encoding.UTF8.GetBytes(testMessage);
while (bytesSent < bytesToSend)
{
int byteToSendThisRound = Math.Min(bufferSize, bytesToSend - bytesSent);
stream.Write(buffer, 0, byteToSendThisRound);
bytesSent += byteToSendThisRound;
}
Client/Receiving Side:
TcpClient client = new TcpClient("127.0.0.1", 13579);
NetworkStream serverStream = client.GetStream();
int totalBytesReceived = 0;
int datacounter = 0;
byte[] recived = new byte[256];
StringBuilder stb = new StringBuilder();
serverStream.ReadTimeout = 1500;
try
{
while ((datacounter = serverStream.Read(recived, 0, 256)) > 0)
{
totalBytesReceived += 256;
Console.WriteLine("RECIVED: {0}, {1}", datacounter, totalBytesReceived);
stb.Append(System.Text.Encoding.UTF8.GetString(recived, 0, datacounter));
}
}
catch { Console.WriteLine("Timeout!"); }
Why don't you dump the exception that makes your code go into the catch branch and find out? :)
catch (Exception ex) { Console.WriteLine("Timeout because of... " + ex.Message); }
--EDIT
Sorry I didn't see the timout. The question you're asking is if there's a way to do it without timeout. Yes, don't set any timeout and check if received number of bytes is smaller than the buffer size.
That is:
while ((datacounter = serverStream.Read(recived, 0, 256)) > 0)
{
Console.WriteLine("RECIVED: " + datacounter.ToString());
stb.append(System.Text.Encoding.UTF8.GetString(recived, 0, datacounter));
if(datacounter < 256) //you're good to go
break;
}
For anyone else who needs help with this
Just to add to Chi_Town_Don's answer, make sure you use stb.ToString() outside of the loop. And I've found that nothing will print out unless the loop breaks out. To do that if(!serverStream.DataAvailable()){break;} works wonders. That way you don't need to pass in the packet size or some other convoluted condition.
I'm working on a biometry system with my C# application.
Sdk provices a connection via TCP/IP on port 2100, and works by receiving and sending strings to communicate .
My class:
class Biometry
{
private System.Net.Sockets.TcpClient _clientSocket = new System.Net.Sockets.TcpClient();
public Biometry() {
//connect to socket
_clientSocket.Connect("127.0.0.1", 2100);
_clientSocket.ReceiveTimeout = 9000;
}
public String identify(String msg) {
//get network stream
NetworkStream _serverStream = _clientSocket.GetStream();
//send an array of bites that represents a string(encoded)
System.Text.ASCIIEncoding ASCII = new System.Text.ASCIIEncoding();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(msg);
_serverStream.Write(outStream, 0, outStream.Length);
//reads the response from networkStream
byte[] inStream = new byte[10025];
_serverStream.Read(inStream, 0, (int)_clientSocket.ReceiveBufferSize);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
_serverStream.Close();
return returndata;
}
}
The problem is:
It is not working!! The biometry only works(SDK only understand my request) when I close the application(connection is closed).
You might need to flush the stream before your start reading using _serverStream.Flush().
Another problem might be that in your question you say you need to connect to port 21000, but in your code you connect to 2100, which might be a typo in either place, but should be fixed ;-)
In addition to flushing the stream, your server might also be waiting for an "end of message" indicator?
I'm doing this for one of my school projects. I'm trying to design a multi-threaded server that accepts clients for working with a database (adding, deleting records etc). When I connect the client to the server I want to receive all the students in my database.
I access the database on the Server Side and store the information in an ArrayList, which I'm trying to send it over the network. I don't have any knowledge on XMLserializing so I'm trying to send each string in the arrayList to the client. When I send the data from the server, I sometimes receive all the data in the same time, sometimes I don't, so my first guess was that I have to split the data I send into packages of some length. I don't see how can I add the length at the beginning of a package. Wouldn't it be the same thing? Maybe I get the correct length maybe I don't.
Here is my code; I didn't try sending the length of each package yet, because I have no idea how. I tried sending from the server the length of the arraylist, and read from the network stream that many times, but it doesn't work ( I receive all data in one package).
Server side:
private void HandleClient(object client)
{
try
{
ClientNo++;
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] bytes = new byte[4096];
int i;
// Robot r = new Robot();
Protocol p = new Protocol();
ArrayList ListaStudentiResponse = p.ExecuteQueryOnStudents("select * from studenti");
byte[] Length = new byte[4];
Length = System.Text.Encoding.ASCII.GetBytes(ListaStudentiResponse.Count.ToString());
clientStream.Write(Length, 0, Length.Length);
foreach ( String s in ListaStudentiResponse)
{
byte[] data = System.Text.Encoding.ASCII.GetBytes(s);
clientStream.Write(data, 0, data.Length);
}
tcpClient.Close();
ClientNo--;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
On Client:
private void connectToServerToolStripMenuItem_Click(object sender, EventArgs e)
{
tcpclient = new TcpClient();
NetworkStream netStream;
try
{
tcpclient.Connect("localhost", 8181);
netStream = tcpclient.GetStream();
Byte[] bytes = new Byte[10000];
int readBytes = netStream.Read(bytes, 0, bytes.Length);
int Length =Int32.Parse(Encoding.ASCII.GetString(bytes, 0, readBytes));
MessageBox.Show(Length.ToString());
int i = 0;
while (i < Length)
{
i++;
Byte[] b = new Byte[10000];
readBytes = netStream.Read(bytes, 0, bytes.Length);
String response = Encoding.ASCII.GetString(b, 0, readBytes);
MessageBox.Show(response);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
You can use a StateObject to keep track of how large your data is, and then test during ReadCallback to see if you have "all" of the message. If you don't have all of your message, you call BeginRecieve again with the current StateObject.
Here is a decent example: http://www.csharphelp.com/2007/02/asynchronous-server-socket-using-c/
This is what I been using:
How to use the buffer on SocketAsyncEventArgs object
Look at the accepted answer. 1st off, this is using something call completion port which is highly efficient than async. Secondly, I find that it is very easy to troubleshoot by looking at e.SocketError to find out the exact cause for failure.
How it works is that for your message to send, append the message with a header and trailer.
So when it receive the message, it will check if the trailer is received. If trailer not received, it will continue receive for that client, and append the received message to the stringBuilder object. Once the trailer is received, just call stringbuilder.toString() to get the whole content.