I am trying to send a request to an existing server solution and write out the results. The server is sending a total of 4 messages with my particular request but the number of messsages back can vary depending on the initial query.
I am able to successfully send the query to the server but when it comes to reading the response i can only read one message. The server logs show that 4 were sent back.
Please help.
IPHostEntry hostEntry = Dns.GetHostEntry(server_textbox.Text);
IPEndPoint endPoint = new IPEndPoint(hostEntry.AddressList[0], port);
string data = String.Empty;
testclient = new TcpClient(server_textbox.Text, port);
testclient.ReceiveBufferSize = 1024;
testclient.SendBufferSize = 1024;
NetworkStream netStream = testclient.GetStream();
Byte[] message_byte = new System.Text.ASCIIEncoding().GetBytes(msg2);
netStream.Write(message_byte, 0, message_byte.Length);
Byte[] returnMessage = new byte[1024];
Int32 totalBytesReceived = 0;
Int32 bytesReceived = 0;
try
{
while ((bytesReceived = netStream.Read(returnMessage, totalBytesReceived, returnMessage.Length)) > 0)
{
totalBytesReceived += bytesReceived;
data += "\n" + ASCIIEncoding.ASCII.GetString(returnMessage);
bytesReceived = 0;
}
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
result_box.Text += data;
netStream.Close();
testclient.Close();
}
My guess is that all your messages are read in the first Read. When the server replies, all the data gets stuck in the windows receive buffer and gets read all at once.
I would recommend using Wireshark, which is more or less mandatory when doing network programming. You'll be able to see the 4 messages coming back from the server as at least 4 different tcp packets.
Related
I am trying to construct an ISO8583 message and it has to be sent to the server using TCP/IP and I should get the response from the server. But I am getting the error. Please help me out.
private static Iso8583 NetworkSend(string ip, int port, Iso8583 msg)
{
// We're going to use a 2 byte header to indicate the message length
// which is not inclusive of the length of the header
var msgData = new byte[msg.PackedLength + 2];
// The two byte header is a base 256 number so we can set the first two bytes in the data
// to send like this
msgData[0] = (byte)(msg.PackedLength % 256);
msgData[1] = (byte)(msg.PackedLength / 256);
// Copy the message into msgData
Array.Copy(msg.ToMsg(), 0, msgData, 2, msg.PackedLength);
// Now send the message. We're going to behave like a terminal, which is
// connect, send, receive response, disconnect
var client = new TcpClient();
var endPoint = new IPEndPoint(IPAddress.Parse(ip), port);
client.Connect(endPoint);
var stream = client.GetStream();
// Send the packed message
stream.Write(msgData, 0, msgData.Length);
// Receive the response
// First we need to get the length of the message out of the socket
var lengthHeader = new byte[2];
stream.Read(lengthHeader, 0,2);//this line im getting error
// Work out the length of the incoming message
var rspLength = lengthHeader[0] * 256 + lengthHeader[1];
var rspData = new byte[rspLength];
// Read the bytes off the network stream
stream.Read(rspData, 0, rspLength);
// Close the network stream and client
stream.Close();
client.Close();
// Parse the data into an Iso8583 message and return it
var rspMsg = new Iso8583();
rspMsg.Unpack(rspData, 0);
return rspMsg;
}
I am trying to send message over TCP/IP in c# application using TCPClient and TCPListner classes
Following is my code which i got from codeproject site.
Client code written over btn click
try
{
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("192.168.0.102", 8001);
// use the ipaddress as in the server program
Console.WriteLine("Connected");
//Console.Write("Enter the string to be transmitted : ");
String str = textBox1.Text;
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
Console.WriteLine("Transmitting.....");
stm.Write(ba, 0, ba.Length);
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 ex)
{
Console.WriteLine("Error..... " + ex.Message);
}
Server code written on form_load
try
{
IPAddress ipAd = IPAddress.Parse("192.168.0.102");
// use local m/c IP address, and
// use the same in the client
/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, 8001);
/* Start Listeneting at the specified port */
myList.Start();
Console.WriteLine("The server is running at port 8001...");
Console.WriteLine("The local End point is :" +
myList.LocalEndpoint);
Console.WriteLine("Waiting for a connection.....");
Socket s = myList.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
byte[] b = new byte[100];
int k = s.Receive(b);
Console.WriteLine("Recieved...");
string str = string.Empty;
for (int i = 0; i < k; i++)
{
Console.Write(Convert.ToChar(b[i]));
str = str + Convert.ToChar(b[i]);
}
label1.Text = str;
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("The string was recieved by the server."));
Console.WriteLine("\nSent Acknowledgement");
/* clean up */
s.Close();
// myList.Stop();
}
Here on client, i m sending string written in textbox over tcp and it well recieved by server.
But when i trying to send another string, it fails without any exception and client application hangs for infinite time.
What is wrong here ?
Server should always be in listening mode, i.e the server code should be in while loop such that it can accept clients continuously. Your server will accept one client and then close itself. Therefore, if you click client's button, a new client tries to connect to server, but now the server won't be available.
Looking at the code you provided, the server only attempts to read 1 message from the client, so needs to be put in a loop to read the multiple incoming messages from the client, process the message and send response and then get more messages.
Note also that the server currently expects only one client to ever connect, processes that client and then closes.
The client is set up basically the same in the example, so you cant modify how one works without also modifying the other.
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.
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.
I am creating a socket server in C# and a client in PHP. The conversation between client and server is something like this:
client connects
server sends welcome message
client sends data
server sends response
(repeat step 3 - 4 until client disconnects)
It works until step 3. The data from the client is received by the server. However, the client waits forever until the server sends its response and eventually times out.
Here is the relevant C# code:
class Program
{
private const int CONNECT_QUEUE_LENGTH = 4;
static void ListenForRequests()
{
Socket listenSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenSock.Bind(new IPEndPoint(IPAddress.Any, 9999));
listenSock.Listen(CONNECT_QUEUE_LENGTH);
listenSock.Blocking = true;
byte[] data = new byte[1024];
while (true)
{
Socket newConnection = listenSock.Accept();
newConnection.Blocking = true;
// Create new thread for each request
var t = new Thread(() => new RequestHandler(newConnection));
t.Start();
}
}
}
class RequestHandler
{
public RequestHandler(Socket socket)
{
Util.WriteToSocket("A message", socket);
Console.WriteLine("Received: " + Util.ReadSocketToEnd(socket).Length);
Util.WriteToSocket("Fin!", socket);
}
}
static class Util
{
public static string ReadSocketToEnd(Socket newConnection)
{
var sb = new StringBuilder();
byte[] data = new byte[1024];
int receivedDataLength = newConnection.Receive(data);
while (receivedDataLength > 0)
{
try
{
sb.Append(Encoding.UTF8.GetString(data, 0, receivedDataLength));
receivedDataLength = newConnection.Receive(data);
}
catch (SocketException)
{
break;
}
}
return sb.ToString();
}
public static void WriteToSocket(string message, Socket client)
{
byte[] data = Encoding.UTF8.GetBytes(message);
client.Send(data, SocketFlags.None);
}
}
And here is the simple PHP client, without any error handling etc:
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$result = socket_connect($socket, '127.0.0.1', 9999);
print 'receiving: ' . chr(10);
print socket_read ($socket, 10) . chr(10);
print 'receive end' . chr(10);
$message = str_repeat("Message to sent", 1000);
socket_write($socket, $message, strlen($message));
print 'message sent' . chr(10);
print 'reading fin' . chr(10); // This is printed, but a response is never received
print socket_read ($socket, 10) . chr(10);
print 'fin read!' . chr(10);
socket_shutdown($socket);
You're reading from the socket until all the data has been read - meaning "all the data until the socket is closed". Your PHP client is writing data, but not closing the socket - so the server is waiting forever.
TCP sockets provide a stream of data. There's no concept of "the end of the current message" which is what it looks like you want.
The three ways of handling this are usually:
A message delimiter (e.g. a line break)
A message length prefix (number of bytes in the message just before the message itself)
Use a different connection for each request/response pair
You could potentially use a read with a timeout, and assume that if you haven't seen any more data in the last 5 seconds, you've got the whole message - but that's fragile, inefficient and generally a bad idea.