async tcp connection C# - c#

TcpListener tcpServer = new TcpListener(8080);
tcpServer.Start();
tcpServer.BeginAcceptTcpClient(new AsyncCallback(this.messageRecived), tcpServer);
I have some code for accept reading from tcp client, client send massage in this way:
TcpClient client = new TcpClient("192.168.0.2", 8080)
string Str = "it's work";
byte[] Buffer = Encoding.ASCII.GetBytes(Str);
client.GetStream().Write(Buffer, 0, Buffer.Length);
the problem is in messageRecived method:
public void messageRecived(IAsyncResult result)
{
byte[] data = new byte[20000];
string outData;
TcpListener server = (TcpListener)result.AsyncState;
server.AcceptTcpClient().GetStream().Read(data, 0, server.Server.ReceiveBufferSize);
outData = Encoding.ASCII.GetString(data);
addLog(outData);
}
When i send message to server the method received run until to this line:
server.AcceptTcpClient().GetStream().Read(data, 0, server.Server.ReceiveBufferSize);
and in the next iteration it begin from next line to the end of method. What is the problem?

probably because you are not closing stream from client, please refer to below link to properly dispose stream from client
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.getstream(v=vs.110).aspx

Try to flush the client Stream.
TcpClient client = new TcpClient("192.168.0.2", 8080)
string Str = "it's work";
byte[] Buffer = Encoding.ASCII.GetBytes(Str);
var stream = client.GetStream()
stream.Write(Buffer, 0, Buffer.Length);
stream.Flush()

Related

Server client communication using Socket C#

I have created an application, which is communicating a server using IP/port. It is sending a ISO request string(Bitmaps in ASCII format) and receiving a response string same format. While Sending the bytes through socket.send and receiving the bytes in socket.receive method. I can see extended ASCII characters are getting changed on other side (Server side/Clint side). I am using below code. Can anyone suggest please, How to resolve the issue.
IPAddress ipAddr = IPAddress.Parse("10.03.0.18");
IPEndPoint localEndPoint = new IPEndPoint(ipAddr, 12345);
// Creation TCP/IP Socket using
// Socket Class Costructor
Socket sender = new Socket(ipAddr.AddressFamily,SocketType.Stream, ProtocolType.Tcp);
sender.Connect(localEndPoint);
string requeststring = AccountValidationRequest();
byte[] messageSent = Encoding.ASCII.GetBytes(requeststring);
int byteSent = sender.Send(messageSent);
byte[] ServerResponse = new byte[1024];
int byteRecv = sender.Receive(ServerResponse);
string ISO8583Message = Encoding.ASCII.GetString(ServerResponse, 0, byteRecv);
Console.WriteLine("Response received from server: --> :{0}", Encoding.ASCII.GetString(ServerResponse, 0, byteRecv));
As it was suggested in comments you should assert that you read all data, not only the first chunk.
Byte[] bytesReceived = new Byte[256];
int bytes = 0;
var ISO8583Message = "Response: \n";
do {
bytes = sender.Receive(bytesReceived, bytesReceived.Length, 0);
ISO8583Message = ISO8583Message + Encoding.ASCII.GetString(bytesReceived, 0, bytes);
}
while (bytes > 0);
There are some nice examples with using sockets on https://learn.microsoft.com/pl-pl/dotnet/api/system.net.sockets.socket?view=netframework-4.8.

TCP Server gets ???????? instead of the real message

The server is written in c# and works correctly with a client I made in c#, now i'm trying to make an android client but the server doesn't get the real message, it gets just a lot of question marks.
Here is the server
TcpListener listen = new TcpListener(IPAddress.Any, 1200);
TcpClient client;
listen.Start();
client = listen.AcceptTcpClient();
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[client.ReceiveBufferSize];
int data = stream.Read(buffer, 0, client.ReceiveBufferSize);
string message = Encoding.Unicode.GetString(buffer, 0, data);
Console.WriteLine(message);
this is the Android client
EditText et = (EditText) findViewById(R.id.EditText01);
String str = et.getText().toString()
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
out.println(str);
For example if I send the message "Hello", the server prints "???????????" and it happens the same for any message I send, even just 1 letter
I also tried with different methods like this one but the result is the same:
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeBytes(str);
Change:
string message = Encoding.Unicode.GetString(buffer, 0, data);
into:
string message = Encoding.UTF8.GetString(buffer, 0, data);
Try also UTF16. I think java uses this encoding now.

Calling method from loop in tcp server c#

I was writing a threaded tcp server and within this thread i wrote this:
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
byte[] buffer = null;
string answer = null;
while (true)
{
bytesRead = 0;
try
{
bytesRead = clientStream.Read(message, 0, 4096);
}
catch(Exception ex)
{
write("Error: " + ex.Message);
break;
}
if (bytesRead == 0)
{
write("Client connection lost!");
break;
}
txtLogger.Text += "Command accepted\n";
ASCIIEncoding encoder = new ASCIIEncoding();
clientreq = encoder.GetString(message, 0, bytesRead);
clientreq = clientreq.ToUpper();
if (clientreq == "CLIENTIP")
{
//THIS PART
answer = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString();
buffer = encoder.GetBytes(answer);
}
//some more if's
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
write("Server finished work.");
}
//some more code
Now i would like the THIS PART to be a method that will be called if the input is CLIENTIP, as requested from client. how i would be doind that.
Thanks in advance :)
By the way, every client req should be handled with new tcp connection.
I've tried this, with pretty bad result: the client freezes and NOTRespondin occured
public void IPKLIENTI()
{
TcpClient client = this.TCPMonitoruesi.AcceptTcpClient();
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] Bufer = null;
string answer = null;
ASCIIEncoding encoder = new ASCIIEncoding();
answer = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString();
Bufer = encoder.GetBytes(answer);
}
To break up your if statement to handle the "CLIENTIP" request, you need to pass the TcpClient you are connected to to the method which does all the work (the IPKLIENTI method) as below.
if (clientreq == "CLIENTIP")
{
// call to IPCLIENTI retrives the RemoteEndPoint of the given TcpClient and encodes a response to be sent
buffer = IPKLIENTI(client, encoder);
}
A revised IPKLIENTI implementation is shown below. The key changes are:
Takes a TcpClient as a paramater rather than accepting a new TcpClient (this behavior lets you work with the TcpClient you recieved the request from and will later respond to, the old behavior attempted to accept another client all together)
Takes an ASCIIEncoding object to do the encoding with - you could re-build it as you used to, but this is tidier and ensures consistency in the future
We don't need to access the NetStream in this function, so we can do away with the call to GetStream
We return an encoded byte array to use as the response to the client when we call clientStream.Write() later in the HandleClientComm function
Revised IPKLIENTI method:
// Method takes a TcpClient Object and Encoder, returning a response to the CLIENTIP request
public byte[] IPKLIENTI(TcpClient tcpClient, ASCIIEncoding encoder)
{
string answer = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString();
byte[] buffer = encoder.GetBytes(answer);
return buffer;
}
Essentially it just stores the intended response in a string (the RemoteEndPoint of the given TcpClient) and then encodes it via the given encoder, returning a byte array of the encoded response to be sent to the client.

Sending long XML over TCP

I'm sending an object (class name House) over TCP using the TcpListener on the server side in response to any message received from the TcpClient.
When the message is received, it is currently populating a text box named textBox1.
If I send a line of text, it works fine. You'll notice that I have a redundant line "Hello, I'm a server" for testing this purpose. But when I send the XML, it is cutting it off prematurely.
When I send serialised XML in to the stream, I'm also receiving this error from the server side:
Unable to read data from the transport connection: An existing
connection was forcibly closed by the remote host.
Here's my server code
// Set the variables for the TCP listener
Int32 port = 14000;
IPAddress ipaddress = IPAddress.Parse("132.147.160.198");
TcpListener houseServer = null;
// Create IPEndpoint for connection
IPEndPoint ipend = new IPEndPoint(ipaddress, port);
// Set the server parameters
houseServer = new TcpListener(port);
// Start listening for clients connecting
houseServer.Start();
// Buffer for reading the data received from the client
Byte[] bytes = new Byte[256];
String data = "hello, this is a house";
// Show that the TCP Listener has been initialised
Console.WriteLine("We have a TCP Listener, waiting for a connection...");
// Continuing loop looking for
while (true)
{
// Create a house to send
House houseToSendToClient = new House
{
house_id = 1,
house_number = 13,
street = "Barton Grange",
house_town = "Lancaster",
postcode = "LA1 2BP"
};
// Get the object serialised
var xmlSerializer = new XmlSerializer(typeof(House));
using (var memoryStream = new MemoryStream())
{
xmlSerializer.Serialize(memoryStream, houseToSendToClient);
}
// Accept an incoming request from the client
TcpClient client = houseServer.AcceptTcpClient();
// Show that there is a client connected
//Console.WriteLine("Client connected!");
// Get the message that was sent by the server
NetworkStream stream = client.GetStream();
// Blank int
int i;
// Loop for receiving the connection from the client
// >>> ERROR IS ON THIS LINE <<<
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
Console.WriteLine("here");
// Take bytes and convert to ASCII string
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received s, return house");
// Convert the string to a byte array, ready for sending
Byte[] dataToSend = System.Text.Encoding.ASCII.GetBytes("Hello, I'm a server");
// Send the data back to the client
//stream.Write(dataToSend, 0, dataToSend.Length);
// Send serialised XML in to the stream
xmlSerializer.Serialize(stream, houseToSendToClient);
}
// Close the connection
client.Close();
}
Client code
// Get the object serialised
var xmlSerializer = new XmlSerializer(typeof(House));
// Set the variables for the TCP client
Int32 port = 14000;
IPAddress ipaddress = IPAddress.Parse("127.0.0.1");
IPEndPoint ipend = new IPEndPoint(ipaddress, port);
string message = "s";
try
{
// Create TCPCLient
//TcpClient client = new TcpClient("localhost", port);
TcpClient client = new TcpClient();
// Convert the string to a byte array, ready for sending
Byte[] dataToSend = System.Text.Encoding.ASCII.GetBytes(message);
// Connect using TcpClient
client.Connect(ipaddress, port);
// Client stream for reading and writing to server
NetworkStream stream = client.GetStream();
// Send the data to the TCP Server
stream.Write(dataToSend, 0, dataToSend.Length);
//xmlSerializer.Serialize(stream, houseToSend);
// Buffer to store response
Byte[] responseBytes = new Byte[256];
string responseData = String.Empty;
// Read the response back from the server
Int32 bytes = stream.Read(responseBytes, 0, responseBytes.Length);
responseData = System.Text.Encoding.ASCII.GetString(responseBytes, 0, bytes);
textBox1.Text = responseData;
// Close the stream and the client connection
stream.Close();
client.Close();
}
catch (SocketException e)
{
MessageBox.Show(e.ToString());
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
I've marked on the code where the error is appearing.
Is it because the message is too long?
Your client code is assuming that the entire message will come through in one call to the Read(...) method, which is absolutely wrong. From the MSDN docs: "An implementation is free to return fewer bytes than requested even if the end of the stream has not been reached."
It's possible that, for a 1024-byte XML document, you may have to call Read(...) 1024 times to get the entire message.
Really, you'd do well to send a four-byte length before you send the XML, so that the client knows how much data to expect. The client will read four bytes, convert that to an integer length, then read that many more bytes, then turn those bytes into XML.

C# client/server Question

I'm incredibly confused as to what is going on here. I've been putting in break points and I just can't seem to understand. Basically, I have a client and a server. I want the client to send two separate strings of data. From putting in break points, I noticed that my client does in fact fill both strings with the appropriate data. However, the server never ever sees the second string. Why is this happening and how do I fix it? Any help at all would be greatly appreciate! Below is my code:
Server:
private static void HandleClientComm(object client)
{
/** creating a list which contains DatabaseFile objects **/
List<DatabaseFile> theDatabase = new List<DatabaseFile>();
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
StringBuilder response = new StringBuilder();
byte[] message = new byte[4096];
int bytesRead;
do
{
bytesRead = 0;
try
{
/*do
{
bytesRead = clientStream.Read(message, 0, message.Length);
response.Append(Encoding.ASCII.GetString(message, 0, bytesRead));
} while (clientStream.DataAvailable);*/
when i change this commented code to bytesRead = clientStream.Read(message, 0, 4096); i get an IOException Error that reads as follows: Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host. Hence, i changed it to a do while loop. How do i get around this IOException and accept the second string?
ASCIIEncoding encoder = new ASCIIEncoding();
String file = encoder.GetString(message, 0, bytesRead);
Menu.Insert(theDatabase, file);
}
catch (Exception)
{
// A socket error has occured
break;
}
if (bytesRead == 0)
{
// The client has disconnected from the server
break;
}
} while (clientStream.DataAvailable);
// Release connections
clientStream.Close();
tcpClient.Close();
}
Client:
static void Main(string[] args)
{
TcpClient client = new TcpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
client.Connect(serverEndPoint);
NetworkStream clientStream = client.GetStream();
NetworkStream clientStream2 = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
ASCIIEncoding encoder2 = new ASCIIEncoding();
String text = System.IO.File.ReadAllText("FirstNames.txt");
String text2 = System.IO.File.ReadAllText("LastNames.txt");
byte[] buffer = encoder.GetBytes(text);
Console.ReadLine();
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
Console.ReadLine();
byte[] buffer2 = encoder2.GetBytes(text2);
clientStream2.Write(buffer2, 0, buffer2.Length);
clientStream2.Flush();
Console.ReadLine();
}
}
The communication between client and server happens like this (note that the order of steps is just for illustration purposes, the actual order at runtime may be different):
Client: client.Connect(serverEndPoint)
Server: HandleClientComm(newClient)
Client: clientStream.Write(buffer, 0, buffer.Length)
Server: bytesRead = clientStream.Read(message, 0, message.Length)
Note that Read is not guaranteed to read entire message. It is perfectly ok to return just the portion that has been received so far
Client: Console.ReadLine()
Server: while (clientStream.DataAvailable)
There is no data on the stream - the client has not sent any. This would likely happen even without ReadLine - there is a window of time before the client sends data again
Server: tcpClient.Close()
Client: clientStream2.Write(buffer2, 0, buffer2.Length)
You can get an exception here, or not - depending on whether the server has already closed the connection, in any case the server is not reading anymore.
You need to define your own message protocol that both server and client will honor. For example, you can have the client close the connection when it is done sending:
Client:
using (var client = new TcpClient("localhost", 8888))
using (var clientStream = client.GetStream())
{
var buffer = Encoding.ASCII.GetBytes( File.ReadAllText("FirstNames.txt") );
clientStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes( File.ReadAllText("LastNames.txt") );
clientStream.Write(buffer, 0, buffer.Length);
}
Server:
using (var tcpClient = (TcpClient)client)
using (var clientStream = tcpClient.GetStream())
{
// Store everything that the client sends.
// This will work if the client closes the connection gracefully
// after sending everything
var receivedData = new MemoryStream();
clientStream.CopyTo(receivedData);
var rawBytes = receivedData.ToArray();
var file = Encoding.ASCII.GetString(rawBytes, 0, rawBytes.Length);
Menu.Insert(theDatabase, file);
}
The protocol is simple, and may be enough for your case. However, there are issues with it which should be addressed in production code (e.g. what if the client sends too much data, exhausting server memory, what if the client stops sending without closing the connection, etc.)
because while (clientStream.DataAvailable) is no longer true after your first client call.
You are exiting your client-recv loop in your server just because DatAvailable is false. This means if the client were to send a frame of data (which you consume) and pause then your server would see no data available at that moment and disconnect, even if a split second later another frame of data from the client was about to come in. Almost always, the end of a dialog is based on the content of the data being passed. You can certainly never try to rely on the fact that DataAvailable happens to be false one time.
As a follow-up, if you provide more info on the protocol that is used we can give more assitance. For example, if the prototcol is that two strings are sent with CR/LF at the end then the server loop should be inspecting the buffer for that to know when to disconnect.

Categories