Connecting to telnet server and send/recieve data - c#

So I am trying to connect to my telnet server, which works. It recives the first lot of data from the server which is us being asked to enter password to connect. But when I type in the password it does nothing and nothing that is recieved is printed to my console.
An example of the output is as follows:
Connected to server.
Please enter password:
Response: MYPASSHERE
__BLANK RESPONSE FROM SERVER__
Response:
I am currently using this code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Threading;
namespace _7DaysServerManager
{
public class ServerSocket
{
private TcpClient client;
private Thread readWriteThread;
private NetworkStream networkStream;
private string password;
public ServerSocket(string ip, int port)
{
try
{
client = new TcpClient(ip, port);
Console.WriteLine("Connected to server.");
}
catch (SocketException)
{
Console.WriteLine("Failed to connect to server");
return;
}
//Assign networkstream
networkStream = client.GetStream();
//start socket read/write thread
readWriteThread = new Thread(readWrite);
readWriteThread.Start();
}
private void readWrite()
{
string command, recieved;
//Read first thing givent o us
recieved = read();
Console.WriteLine(recieved);
//Set up connection loop
while (true)
{
Console.Write("Response: ");
command = Console.ReadLine();
if (command == "exit")
break;
write(command);
recieved = read();
Console.WriteLine(recieved);
}
Console.WriteLine("Disconnected from server");
networkStream.Close();
client.Close();
}
public void write(string message)
{
networkStream.Write(Encoding.ASCII.GetBytes(message), 0, message.Length);
networkStream.Flush();
}
public string read()
{
byte[] data = new byte[1024];
string recieved = "";
int size = networkStream.Read(data, 0, data.Length);
recieved = Encoding.ASCII.GetString(data, 0, size);
return recieved;
}
}
}

I believe you need your code to look more like this:
message += Environment.NewLine;
byte[] messageBytes = Encoding.ASCII.GetBytes(message);
networkStream.Write(messageBytes, 0, messageBytes.Length);
I.e. if you don't terminate the password with a newline character, the server doesn't know you're done entering the password (TCP is not message-oriented, so the fact that you didn't continue sending bytes in no way provides any indication that you're done sending the password).
Note also that you should use the actual length of the byte[] returned from GetBytes() as the length of the data. For ASCII, it's true you can compute the number of bytes trivially from the message length, but using the actual byte count is a good habit to get into. You may not always be dealing with ASCII in networking code.
Finally, I will suggest that you change your code in a couple of ways:
Wrap the NetworkStream in StreamReader and StreamWriter instances, to make sending and receiving text easier (don't forget to set the encoding to Encoding.ASCII for the reader and writer).
Read and write in different threads. Or even better, use StreamReader.ReadLineAsync() so that the reading is done asynchronously without an explicit thread.
If you don't switch to StreamReader, you should still read (asynchronously or not) in a different thread, and don't forget that you need to keep reading from the buffer all the time, as a response from the server may or may not be received in a single call to Read().

Related

How can I send multiple string messages from client to server using a single instance of TcpClient?

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?

c# tcpclient program writing to stream but client not receiving data

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

Socket writing not working properly c#

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?

How to send length of a package via tcp/ip protocol

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.

Sending and receiving custom objects using Tcpclient class in C#

I have a client server application in which the server and the client need to send and receive objects of a custom class over the network. I am using TcpClient class for transmitting the data. I am serializing the object at the sender side and sending the resulting stream of bytes to the receiver. But at the receiver, when I try to de-serialize the bytes received, it throws Serialization Exception and the details are :
The input stream is not a valid
binary format. The starting contents
(in bytes) are:
0D-0A-00-01-00-00-00-FF-FF-FF-FF-01-00-00-00-00-00
...
My server code that serializes the object is:
byte[] userDataBytes;
MemoryStream ms = new MemoryStream();
BinaryFormatter bf1 = new BinaryFormatter();
bf1.Serialize(ms, new DataMessage());
userDataBytes = ms.ToArray();
netStream.Write(userDataBytes, 0, userDataBytes.Length);
The client code that de-serializes it is:
readNetStream.Read(readMsgBytes, 0, (int)tcpServer.ReceiveBufferSize);
MemoryStream ms = new MemoryStream(readMsgBytes);
BinaryFormatter bf1 = new BinaryFormatter();
ms.Position = 0;
object rawObj = bf1.Deserialize(ms);
DataMessage msgObj = (DataMessage)rawObj;
Please help me to solve this problem and possibly suggest any other method to transmit objects of custom classes across network using TcpClient in C#.
Thanks,
Rakesh.
Have a look at this code. It takes a slightly different approach.
Example given by the link above: - Note: there was another problem he was facing which he solved here (keep-alive). It's in the link after the initial sample code.
Object class to send (remember the [Serializable]):
[serializable]
public class Person {
private string fn;
private string ln;
private int age;
...
public string FirstName {
get {
return fn;
}
set {
fn=value;
}
}
...
...
public Person (string firstname, string lastname, int age) {
this.fn=firstname;
...
}
}
Class to send object:
using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
class DataSender
{
public static void Main()
{
Person p=new Person("Tyler","Durden",30); // create my serializable object
string serverIp="192.168.0.1";
TcpClient client = new TcpClient(serverIp, 9050); // have my connection established with a Tcp Server
IFormatter formatter = new BinaryFormatter(); // the formatter that will serialize my object on my stream
NetworkStream strm = client.GetStream(); // the stream
formatter.Serialize(strm, p); // the serialization process
strm.Close();
client.Close();
}
}
Class to receive object:
using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
class DataRcvr
{
public static void Main()
{
TcpListener server = new TcpListener(9050);
server.Start();
TcpClient client = server.AcceptTcpClient();
NetworkStream strm = client.GetStream();
IFormatter formatter = new BinaryFormatter();
Person p = (Person)formatter.Deserialize(strm); // you have to cast the deserialized object
Console.WriteLine("Hi, I'm "+p.FirstName+" "+p.LastName+" and I'm "+p.age+" years old!");
strm.Close();
client.Close();
server.Stop();
}
}
When receiving on client side you do not know how much data you want to read.
You are only relying on the ReceiveBufferSize, while your data can be larger
or smaller then that.
I think the best approach here is to send 4 bytes that tells your client about the length of incoming data:
byte[] userDataLen = BitConverter.GetBytes((Int32)userDataBytes.Length);
netStream.Write(userDataLen, 0, 4);
netStream.Write(userDataBytes, 0, userDataBytes.Length);
and on the recieving end you first read the data length and then read
exact amount of data.
byte[] readMsgLen = new byte[4];
readNetStream.Read(readMsgLen, 0, 4);
int dataLen = BitConverter.ToInt32(readMsgLen);
byte[] readMsgData = new byte[dataLen];
readNetStream.Read(readMsgData, 0, dataLen);
Infact, I just realized, that you might has to do a little more to assure you read all data (just an idea because I haven't tried it, but just incase you run into problem again you can try this).
The NetworkStream.Read() method returns a number indicating the amount of data it has read. It might be possible that the incoming data is larger then the RecieveBuffer. In that case you have to loop until you read all of the data. You have to do something like this:
SafeRead(byte[] userData, int len)
{
int dataRead = 0;
do
{
dataRead += readNetStream.Read(readMsgData, dataRead, len - dataRead);
} while(dataRead < len);
}
TCP is stream-based protocol (as opposed to datagram protocol) so it's possible to receive only part of sended data via Read method call.
To solve this problem you may use DataLength field (as cornerback84 suggested) or you may use your own "application-level packet" structure.
For example, you may use something like this
|-------------------------------|
|Begin|DataLength| Data |End|
| 4b | 4b | 1..MaxLen|4b |
|-------------------------------|
where
Begin - start packet identifier (for example 0x0A, 0x0B, 0x0C, 0x0D)
DataLength - Data field length (for example, from 0 to MaxLength)
Data - actual data (serialized Person class or some other data)
End - end packet identifier (for example 0x01, 0x05, 0x07, 0x0F).
That is, on client side you would wait not only for incoming data, after receiving data you would search you Application level packets, and you may deserialized Data part only after receiving valid packet.

Categories

Resources