Unable to send acknowledgemnt properly in TCP connection (C#) - c#

I have a client server model.
192.168.77.6 is the client (my code). 192.168.77.18 is a server device. I am sending a request to the server for a response. Once I get the response, I am reading the response and trying to send an acknowledgement of 2 bytes (line 479 of wireshark packet). But, before I can send my acknowledgement, I see that an acknowledgement of 0 bytes is being sent from the client (line 429 of wireshark packet), which causes the server device to send a [FIN,ACK] packet (line 475 of wireshark packet), and it doesn't accept the acknowledgement that I am sending (line 479 of wireshark packet).
Below is the screenshot of the wireshark packets obtained:
Wireshark packet screenshot
I have included my code below:
TcpClient tcpclnt;
NetworkStream stream;
tcpclnt = new TcpClient();
tcpclnt.Connect(ip, port);
stream = tcpclnt.GetStream();
if (tcpclnt.Connected)
{
SendMessage(stream, RequestToSend);
Thread.Sleep(2000);
string readData = "";
readData = readBytes1(stream);
}
tcpclnt.Close();
Below is the readBytes1() function:
private static string readBytes1(NetworkStream stream)
{
byte[] resp = new byte[100];
var memoryStream = new MemoryStream();
int bytes;
do
{
bytes = 0;
bytes = stream.Read(resp, 0, resp.Length);
memoryStream.Write(resp, 0, bytes);
}
while (bytes > 0);
GenerateAcknowledgement(stream);
return Encoding.GetEncoding("ISO-8859-1").GetString(memoryStream.ToArray());
}
GenerateAcknowledgement() is the function that sends 2 bytes of data.

You need to obtain the server and protocol.
The server is closing the connection. This will be in the design of the server.
It's possible that you're not doing something in the request to the server which causes it to close immediately.
Without knowing the protocol or having the server code it's not possible to know why the the server is closing the connection.

Related

Connecting to Serial->Ethernet converter box via Telnet, getting strange response (no matter what I send)

I'm trying to communicate with a device that has a Serial COM port that goes out (using RS232 Protocol), which I've hooked up to a converter box that converts the connection to Ethernet.
I've successfully connected to the converter box (which has its own IP) and I've successfully communicated with the device by sending it commands over telnet by using PuTTY, to which it has responded with various data that I've been able to parse.
I've established a connection by creating a new TcpClient, and I'm able to send strings to the device, but every time I get a response back, it's always "??\u0003" which I've researched and found that \uhhhh is a Unicode escape protocol. This confuses me because I have used ASCII encoding for everything.
public string TcpConnect(string cmd)
{
var client = new TcpClient();
//cmd = "ping";
Console.WriteLine("Connecting to server");
client.Connect("169.254.20.40", 23); //22 = ssh, 23 = telnet, 80 = http
Console.WriteLine("CONNECTED SUCCESSFULLY");
Stream tcpStream = client.GetStream();
ASCIIEncoding A = new ASCIIEncoding();
byte[] enable = A.GetBytes("enable" + Environment.NewLine);
byte[] connect = A.GetBytes("connect line 1" + Environment.NewLine);
byte[] ba = A.GetBytes(cmd);
Console.WriteLine("Transmitting.....");
tcpStream.Write(enable, 0, enable.Length);
tcpStream.Write(connect, 0, connect.Length);
tcpStream.Write(ba, 0, ba.Length);
byte[] responseBytes = new byte[4096];
int numBytesRead = tcpStream.Read(responseBytes, 0, responseBytes.Length);
var message = A.GetString(responseBytes, 0, numBytesRead);
Console.WriteLine("\nServer Closed.");
return message;
}
If I were to pass in "$TEAA4B9\r\n" as the message, I would expect something along the lines of "$TEA,086,040,031,000,3798" which is nowhere close to what I'm getting (which is ??\u0003)
Nevermind figured it out
Just kidding! Here's what I did: I added a "System.Threading.Thread.Sleep("1000") before the "tcpStream.Read" line at the bottom, and now it outputs the data I need. The device was outputting garbage on the first line (perhaps a handshake, not sure) and that's all that was being read before it was being stored into "message" and returned (not enough time was spent reading before it moved on to the next line of code)

STOR command destroys connection with FTP server

I am writing FTP client with C#. I typed methods to upload file to FTP server and file upload does work. However, after successful data transmission, client gets disconnected from server. Here are steps I do:
1. Get IP and Port from server by using PASV.
2. Create DATA connection with server using IP and port.
3. Convert file to bytes and send through DATA connection.
4. Send STOR through COMMAND connection
My question is why I get disconnected.
public void PrepareUpload() // Get IP and Port from server by using PASV.
{
String answer;
String message = "PASV\r\n";
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
this.ns.Write(data, 0, data.Length);
answer = Response(this.ns);
this.dataPort = getPort(answer, 4) * 256 + getPort(answer, 5);
}
public void DataConnect(string server) // Create DATA connection with server using IP and port.
{
int port = this.dataPort;
this.dataConnection = new TcpClient();
IPAddress ipAddress = Dns.GetHostEntry(server).AddressList[0];
this.dataConnection.Connect(ipAddress, port);
this.nds = dataConnection.GetStream();
}
public void DataTransfer(string filename) // Convert file to bytes and send through DATA connection.
{
byte[] data = System.IO.File.ReadAllBytes(filename);
this.filename = Path.GetFileName(filename);
nds.Write(data, 0, data.Length);
}
public void Upload() // Send STOR through COMMAND connection
{
String message = "STOR " + this.filename + "\r\n";
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
this.ns.Write(data, 0, data.Length);
}
The order you describe is wrong. In particular you should not start data transfer before issuing the command which specifies what should happen with the transferred data (i.e. STOR). The correct order would be:
Use PASV or PORT command to determine data port and get response to this command. In case of PORT listen on the given IP:port.
Send the STOR command and read the response. It should be a preliminary response (150).
Create the data connection: with PASV connect to the remote host, with PORT wait for an incoming connections.
Transfer the data and close the data connection.
Wait for the final response (226).

Minecraft Server Ping with C# [duplicate]

So found this little code snippet that would allow you to ping a Minecraft server in PHP, but now i want to do this in C#.
I tried doing this on my own but for some reason its just not working
UdpClient client = new UdpClient();
IPEndPoint ep;
try
{
ep = new IPEndPoint(IPAddress.Parse("-snip-"), -snip-);
client.Connect(ep);
}
catch { Console.WriteLine("Error"); Console.ReadLine(); return; }
byte[] bytes = new byte[1];
bytes[0] = (byte)0xFE;
client.Send(bytes, bytes.Length);
IPEndPoint rep = new IPEndPoint(IPAddress.Any, 0);
byte[] recv = client.Receive(ref rep);
Console.WriteLine(ASCIIEncoding.ASCII.GetString(recv));
Console.ReadLine();
The server seems to just completely ignore the packet. This is the code snippet i found:
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
if (!$fp) return false;
//Send 0xFE: Server list ping
fwrite($fp, "\xFE");
//Read as much data as we can (max packet size: 241 bytes)
$d = fread($fp, 256);
//Check we've got a 0xFF Disconnect
if ($d[0] != "\xFF") return false;
Could anyone please point out what mistake i'm making? Thank you!
As described here
The client initiates a TCP connection to the minecraft server on the
standard port. Instead of doing auth and logging in (as detailed in
Protocol Encryption), it sends the two byte sequence FE 01. This is a
0xFE server list ping packet. If the second byte (the 0x01) is
missing, the server waits about 1000ms then replies with the Server ->
Client format used in 1.3 and earlier.
you need to send a TCP request whereas you're sending an UDP packet...

C# TCP NetworkStream missing a few bytes of data

I'm having two problems and after trying a few techniques I've read on stackoverflow, the problem persists. I'm trying to send a file from the server to client with the following code below but the problem is that the file is always a few bytes short, causing file corruption.. The second problem is that the stream doesn't close despite implementing a zero length packet at the end to indicate the transfer is finished without closing the connection.
Server code snippet:
/*
* Received request from client for file, sending file to client.
*/
//open file to send to client
FileStream fs = new FileStream(fileLocation, FileMode.Open, FileAccess.Read);
byte[] data = new byte[1024];
long fileSize = fs.Length;
long sent = 0;
int count = 0;
while (sent < fileSize)
{
count = fs.Read(data, 0, data.Length);
netStream.Write(data, 0, count);
sent += count;
}
netStream.Write(new byte[1024], 0, 0); //send zero length byte stream to indicate end of file.
fs.Flush();
netStream.Flush();
Client code snippet:
TcpClient client;
NetworkStream serverStream;
/*
* [...] client connect
*/
//send request to server for file
byte[] dataToSend = SerializeObject(obj);
serverStream.Write(dataToSend, 0, dataToSend.Length);
//create filestream to save file
FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
//handle response from server
byte[] response = new byte[client.ReceiveBufferSize];
byte[] bufferSize = new byte[1024];
int bytesRead;
while ((bytesRead = serverStream.Read(bufferSize, 0, bufferSize.Length)) > 0 && client.ReceiveBufferSize > 0)
{
Debug.WriteLine("Bytes read: " + bytesRead);
fs.Write(response, 0, bytesRead);
}
fs.Close();
With UDP you can transmit an effectively empty packet, but TCP won't allow you to do that. At the application layer the TCP protocol is a stream of bytes, with all of the packet-level stuff abstracted away. Sending zero bytes will not result in anything happening at the stream level on the client side.
Signalling the end of a file transfer can be as simple as having the server close the connection after sending the last block of data. The client will receive the final data packet then note that the socket has been closed, which indicates that the data has been completely delivered. The flaw in this method is that the TCP connection can be closed for other reasons, leaving a client in a state where it believes that it has all the data even though the connection was dropped for another reason.
So even if you are going to use the 'close on complete' method to signal end of transfer, you need to have a mechanism that allows the client to identify that the file is actually complete.
The most common form of this is to send a header block at the start of the transfer that tells you something about the data being transferred. This might be as simple as a 4-byte length value, or it could be a variable-length descriptor structure that includes various metadata about the file such as its length, name, create/modify times and a checksum or hash that you can use to verify the received content. The client reads the header first, then processes the rest of the data in the stream as content.
Let's take the simplest case, sending a 4-byte length indicator at the start of the stream.
Server Code:
public void SendStream(Socket client, Stream data)
{
// Send length of stream as first 4 bytes
byte[] lenBytes = BitConverter.GetBytes((int)data.Length);
client.Send(lenBytes);
// Send stream data
byte[] buffer = new byte[1024];
int rc;
data.Position = 0;
while ((rc = data.Read(buffer, 0, 1024)) > 0)
client.Send(buffer, rc, SocketFlags.None);
}
Client Code:
public bool ReceiveStream(Socket server, Stream outdata)
{
// Get length of data in stream from first 4 bytes
byte[] lenBytes = new byte[4];
if (server.Receive(lenBytes) < 4)
return false;
long len = (long)BitConverter.ToInt32(lenBytes, 0);
// Receive remainder of stream data
byte[] buffer = new byte[1024];
int rc;
while ((rc = server.Receive(buffer)) > 0)
outdata.Write(buffer, 0, rc);
// Check that we received the expected amount of data
return len == outdata.Position;
}
Not much in the way of error checking and so on, and blocking code in all directions, but you get the idea.
There is no such thing as sending "zero bytes" in a stream. As soon as the stream sees you're trying to send zero bytes it can just return immediately and will have done exactly what you asked.
Since you're using TCP, it is up to you to use an agreed-upon protocol between the client and server. For example:
The server could close the connection after sending all its data. The client would see this as a "Read" that completes with zero bytes returned.
The server could send a header of a fixed size (maybe 4 bytes) that includes the length of the upcoming data. The client could then read those 4 bytes and would then know how many more bytes to wait for.
Finally, you might need a "netStream.Flush()" in your server code above (if you intended to keep the connection open).

Read bytes from NetworkStream (Hangs)

I'm trying to learn the basics of networking and I've built an echo server from this tutorial. I checked the server with telnet and it works perfect.
Now when I'm using some of the many client samples on the Internet:
// Create a TcpClient.
// Note, for this client to work you need to have a TcpServer
// connected to the same address as specified by the server, port
// combination.
TcpClient client = new TcpClient(server, port);
// Translate the passed message into ASCII and store it as a Byte array.
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
// Get a client stream for reading and writing.
NetworkStream stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", message);
// Receive the TcpServer.response.
// Buffer to store the response bytes.
data = new Byte[256];
// String to store the response ASCII representation.
String responseData = String.Empty;
// Read the first batch of the TcpServer response bytes.
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", responseData);
// Close everything.
stream.Close();
client.Close();
It doesn't work very well. If I will comment the stream.Read line, everything works perfect (expect I can't read). I was also trying to accomplish that in a similar way using asynchronous callback method for the read. and then it only works after I terminate the program (the server handles the request)
I suspect that the way I'm reading from the stream cause this block, but I'm too clueless to understand what I'm doing wrong.
The implementation will block until at least one byte of data can be
read, in the event that no data is available.
From MSDN
Your server propably isn't sending you any data.
Edit:
I tested your client and it works perfectly fine. Try it yourself and set the following parameters:
string server = "google.com";
int port = 80;
string message = "GET /\n";
It's definitely your server which has the problem.

Categories