Im trying to build a small compact telnet tool
therefor I've decided to tackle the sending without waiting for response part first
the problem is that no matter which guide I use I just cant make it work
what am I missing here ??
public void SendTelnetCommand(string Command , string IPofAP)
{
IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(IPofAP), 23);
TcpClient tcpSocket;
tcpSocket = new TcpClient(endpoint);
if (!tcpSocket.Connected) return;
byte[] buf = System.Text.ASCIIEncoding.ASCII.GetBytes(Command);
tcpSocket.GetStream().Write(buf, 0, buf.Length);
if (tcpSocket.Connected) tcpSocket.Close();
}
while debuging I get An unhandled exception of type 'System.Net.Sockets.SocketException' in System.dll
What's the message of the exception? Any inner exceptions? Are you using the correct IP address (IPv4 or IPv6?)? Also, you have to read from the stream as well.
However, your issue is most likely using the wrong TcpClient constructor. The one that takes the endpoint is a listener, not a client. You have to use the hostname + port overload.
That is, try this:
public void SendTelnetCommand(string Command, string IPofAP)
{
TcpClient tcpSocket = new TcpClient(IPofAP, 23);
if (!tcpSocket.Connected) return;
byte[] buf = System.Text.ASCIIEncoding.ASCII.GetBytes(Command);
tcpSocket.GetStream().Write(buf, 0, buf.Length);
if (tcpSocket.Connected) tcpSocket.Close();
}
You can also use the IPEndPoint to connect to a server, however, you have to use the parameter-less constructor, and call tcpSocket.Connect(endpoint);
Related
So, I'm developing a client-side application in C# that connects to a server side application (also written in C#). To begin with, I am just trying to get the applications to successfully communicate with one another. Currently, I have both the client and server running on the same device.
Server Side
On the server side, I'm using a TcpListener to accept a socket, printing out that it has connected for debugging purposes, receiving a request, and sending a response. The code can be found below:
Server Side Code:
while (true)
{
// Accept a new connection
Socket socket = socketListener.AcceptSocket();
if (socket.Connected)
{
Console.WriteLine("\nClient Connected!!\n==================\nClient IP {0}\n", socket.RemoteEndPoint);
// Make a byte array and receive data from the client
byte[] receive = new byte[1024];
_ = socket.Receive(receive, receive.Length, 0);
// Convert byte to string
string buffer = Encoding.ASCII.GetString(receive);
string response = "Test response";
int numBytes = 0;
try
{
if (socket.Connected)
{
if ((numBytes = socket.Send(data, data.Length, 0)) == -1)
Console.WriteLine("Socket Error: cannot send packet");
else
Console.WriteLine("No. of bytes sent {0}", numBytes);
}
else
{
Console.WriteLine("Connection Dropped...");
}
}
catch (Exception e)
{
Console.WriteLine("An exception has occurred: " + e.ToString());
}
}
}
Client Side
On the client side, I'm using a TcpClient to connect to the server using an IP address (In this case it's 127.0.0.1), establishing a NetworkStream object, sending a request, and reading a response.
Client-Side Code:
private static readonly TcpClient socket = new TcpClient();
private const string IP = "127.0.0.1";
private const int PORT = 46495;
static void Main(string[] args)
{
try
{
socket.Connect(IP, PORT);
}
catch (Exception)
{
Console.WriteLine("Error connecting to the server.");
return;
}
NetworkStream stream = socket.GetStream();
stream.ReadTimeout = 2000;
string request = "Test Request";
byte[] bytes = Encoding.UTF8.GetBytes(request);
stream.Write(bytes, 0, bytes.Length);
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
try
{
string response = reader.ReadToEnd();
Console.WriteLine(response);
}
catch(Exception e)
{
Console.WriteLine(e);
}
}
The Output
On the server side, everything appears to be fine. The client connects successfully with the expected IP address, I get the expected request, and the correct response appears to have been sent successfully.
The client-side is where it gets more complicated. Where I would expect the "Test Response" response, instead I get a SocketException that from what I understand indicates a timeout??? The full output can be found below:
System.IO.IOException: Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or an established connection failed because the connected host has failed to respond...
---> System.Net.Sockets.SocketException (10060): A connection attempt failed because the connected party did not properly respond after a period of time, or an established connection failed because the connected host has failed to respond.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.IO.StreamReader.ReadBuffer()
at System.IO.StreamReader.ReadToEnd()
at Client.Client.Main(String[] args) in C:\Dev\Project Orange Sunshine\Project Orange Sunshine\Client\Client.cs:line 38
What I have tried
To begin I wanted to ensure that my server was in fact sending a response in the first place. To test this, I tried accessing the server application through a web browser. Sure enough, I got a blank page with the expected "Test Response" text in the top left corner. This, to me, indicates my server application is working as expected.
Through some googling, I have found a variety of answers to similar questions stating that it is likely that the Windows Defender Firewall is blocking the port that is being used. For testing purposes, I tried disabling the firewall entirely for private networks such as the one that I am on. This didn't change anything, unfortunately.
I feel like I am missing something obvious and any input would be greatly appreciated.
Cheers!
StreamReader.ReadToEnd() on a NetworkStream will only return once the "end" of the stream is reached, which doesn't happen in your example; thus, the StreamReader times out.
You should fix this by using the lower-level NetworkStream.Read method to read from the stream:
var buffer = new byte[4096];
var bytesRead = stream.Read(buffer, 0, buffer.Length);
Console.WriteLine("Read {0} bytes", bytesRead);
string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine(response);
To make this test program more robust, you will also need to introduce "framing", i.e., some way for the server to indicate to the client that it can stop reading. This can be a terminator suffix, such as \r\n used by HTTP, or a length prefix that is sent upfront to tell the client how many more bytes to read.
I have an embedded Ethernet interface (Lantronix XPort) that responds to a UDP broadcast with its identifying information.
I am able to multicast the "magic packet" and datagrams are received by the listener correctly, however I also need to find out what IP Address send that response datagram. If it were TCP, I would do socket.RemoteEndPoint, but that throws an exception when applied to a UDP socket.
public class Program
{
public static void Main(string[] args)
{
// magic packet
byte[] magicPacket = new byte[4] { 0, 0, 0, 0xf6 };
// set up listener for response
Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// EDIT: Also, had to add this to for it to broadcast correctly
sendSocket.EnableBroadcast = true;
IPEndPoint listen_ep = new IPEndPoint(IPAddress.Any, 0);
sendSocket.Bind(listen_ep);
// set up broadcast message
EndPoint send_ep = new IPEndPoint(IPAddress.Parse("192.168.255.255"), 30718);
sendSocket.SendTo(magicPacket, magicPacket.Length, SocketFlags.None, send_ep);
DateTime dtStart = DateTime.Now;
while (true)
{
if (sendSocket.Available > 0)
{
byte[] data = new byte[2048];
// throws SocketException
//IPEndPoint ip = sendSocket.RemoteEndPoint as IPEndPoint;
sendSocket.Receive(data, SocketFlags.None);
if (data.Length > 4)
{
PrintDevice(data);
}
}
if (DateTime.Now > dtStart.AddSeconds(5))
{
break;
}
Console.WriteLine(".");
Thread.Sleep(100);
}
// wait for keypress to quit
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
Any thoughts? Is there a better strategy to reading the response datagrams that would let me ascertain the Remote IP Address?
EDIT:
As is typical, the minute I post on SO, a moment of clarity hits me.
Turns out I can just do this:
EndPoint remote_ep = new IPEndPoint(IPAddress.Any, 0);
// Use ReceiveFrom instead of Receieve
//sendSocket.Receive(data, SocketFlags.None);
sendSocket.ReceiveFrom(data, ref remote_ep);
And remote_ep now contains the remote endpoint information!
Take a look at ReceiveFrom instead of Receive, it will let you pass in a reference to an Endpoint.
What about Asynchronous socket?I didn't find any way to get the remote IP address. (Asynchronous method ReceiveFromAsync is my only option in wp8)
EndPoint remote_ep = new IPEndPoint(IPAddress.Any, 0); // Use ReceiveFrom instead of
sendSocket.Receive(data, SocketFlags.None);
sendSocket.ReceiveFrom(data, ref remote_ep);
i think it works for IP but it fails for port number
if you would notice
try chaging 0 to something else like 6530 4expl
it system will would generate it's random port number
Any ideas to why is it ?
P.S. Any ideas how can i change my user name here .... ?
FOUND IT : the abstract class only needed for representation of port it is in value not out
since there's no bind done before hand this operation ref EndPoint needed to represent the sender. Meaning that it is there to show senders port and IP not to specify from where to get the communication. And EndPoint instantiation is really just a formality seems like it is overriden by system with senders address anyway. I think it has to do somethign with the way UDP protocol works.
But all in all the ref EndPoint is there only shows where u got the packet from and only it does not specify where u want u'r commuicatino to be from.
I cannot get this example to run:
https://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient%28v=vs.110%29.aspx
The only thing Ive changed with their code is to put everything in the main method, and my port name of course. I Can connect to my server, and even send data. But on the line
Int32 bytes = networkStream.Read(data, 0, data.Length);
The program stops running without an exception. How can microsoft own code not work? My server doesnt send anything yet, but I dont think that should matter? (It recieves perfectly though.) Ive Read something that you cannot se exceptions in other threads, but I dont have any.
I also tried this thread:
C# tcp socket (networkstream.read won't work with 8.1)
It doesnt work. I run win 7 thoguh. But I wish this to work an all new windows.
NetworkStream.Read blocks until data is available, the connection is closed (it will return 0 in that case) or an exception occurs. It is designed that way.
If your server would send data, your client program would continue and be able to process the response.
NetworkStream.Read() is a synchronous call, it will wait till a response is received. To read data of different lengths, you can do something like below.
NOTE: I'm assuming server is sending only one response for a request.
private string GetResponse(string command)
{
//Send request
TcpClient client = new TcpClient(HOST, PORT);
Byte[] data = Encoding.ASCII.GetBytes(command);
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
//Read response
data = new Byte[BUFFER_SIZE];
String response = String.Empty;
stream.ReadTimeout = READ_TIMEOUT;
while (!response.EndsWith(RESPONSE_END))
{
int bytes = stream.Read(data, 0, data.Length);
response += Encoding.ASCII.GetString(data, 0, bytes);
}
response = response.Remove(response.Length - RESPONSE_END.Length);
stream.Close();
client.Close();
//Return
return response;
}
I believe what I am looking to create is a service that listens to a specific port, and when data is sent to that port, it sends off that data to another script for processing.
For some reason though, the service times out when I try to start it. My logs tells me TcpClient client = server.AcceptTcpClient(); is where it is stopping (actually, it is getting stuck on 'starting' in Services).
Since I have no experience with C#, making services, or working with servers in this manner, the code is pretty much just what I found online.
The OnStart method looks like this.
protected override void OnStart(string[] args)
{
try
{
TcpListener server = null;
// Set the TcpListener on port 13000.
Int32 port = 1234;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
// Buffer for reading data
Byte[] bytes = new Byte[256];
String data = null;
// Enter the listening loop.
while (true)
{
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
data = null;
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
// Process the data sent by the client.
data = data.ToUpper();
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
// Send back a response.
stream.Write(msg, 0, msg.Length);
}
// Shutdown and end connection
client.Close();
}
}
catch (SocketException e)
{
}
finally
{
}
}
As per MSDN, TcpServer.AcceptTcpClient blocks, so you're probably never returning from your Service's OnStart method, which causes the service to never actually "start".
You might consider using another thread and return from OnStart as soon as possible.
Cheers
As far as creating the Windows service itself, you should be able to use this link, even though it's dated. This companion link shows how to have the service install and uninstall itself. Finally, use this link to understand how to have your service run constantly and how to properly respond to start and stop commands.
To have your service interact with the socket, you'll want to modify the WorkerThreadFunc() from the last link. This is where you should start listening for and processing inbound socket connections.
I'm having some problems with an app i created. The general situation (the following description is not 1-1 related to question): I have a WCF client-server app for collecting data at multiple sites. The client retrieves local data (some files etc), sends it to the server in the datacenter and this server processes it. The client gets most of its data from the localhost, but some of it is retrieved from different servers on the LAN. Here's where my problem starts. I had to create a 3rd app which sends data to the stated client. In the reminder of this post i refer to client and server as the to apps on the same LAN (so not the server in the datacenter above)
I tried using named pipes, which went superb interprocess on the same host, but was immense slow server-to-server. (if anyone has thoughts on why this is plz dont hesitate to tell me. Some tests went up to 1000 ms sending and receiving just a few bytes)
So i went to using the TcpClient class. Tests showed responses much faster than the NP equivalents, so i decided to go with this option.
Now, when client and server start and end both as they are supposed to do, everything is fine. The problem arrises when the server is fired up, the client has connected, server is waiting its stream.Read() method, and then the client app exits:
Unable to read data from the transport connection: De externe host heeft een verbinding verbroken. (2nd part translation: An existing connection was forcibly closed by the remote host.)
At the moment i wrapped the whole part with a Try-Catch statement, restarting the whole thing on a IoException. This does work, but as i read several posts on "An exception should be something exceptional!", it does not feel well.
So finally the question: How can this exception been avoided?
(What is the normal way to keep a connection between server and client app in real life?)
Server
TcpListener serverSocket = new TcpListener(System.Net.IPAddress.Any, 8888);
TcpClient clientSocket = default(TcpClient);
while (true)
{
serverSocket.Start();
clientSocket = serverSocket.AcceptTcpClient();
while ((true))
{
try
{
NetworkStream networkStream = clientSocket.GetStream();
byte[] bytesFrom = new byte[10025];
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);//THIS THROWS THE EXCEPTION WHEN A CLIENT QUITS
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
Console.WriteLine(" >> Data from client - " + dataFromClient);
string serverResponse = "Server response " + DateTime.Now.ToString("HH:mm:ss,fff");
Byte[] sendBytes = Encoding.ASCII.GetBytes(serverResponse);
int len = sendBytes.Length;
networkStream.WriteByte((byte)(len / 256));
networkStream.WriteByte((byte)(len & 255));
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
}
catch (System.IO.IOException ex)
{
Console.WriteLine(ex.ToString());
break;
}
}
clientSocket.Close();
serverSocket.Stop();
}
}
client
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
private void button2_Click(object sender, EventArgs e)
{
NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes("Message from Client$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
int len = serverStream.ReadByte() * 256;
len += serverStream.ReadByte();
byte[] inStream = new byte[len];
serverStream.Read(inStream, 0, len);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
msg("Data from Server : " + returndata);
}
private void button1_Click_1(object sender, EventArgs e)
{
clientSocket.Connect("127.0.0.1", 8888);
}
My understanding of the Socket API is that you are supposed to call Shutdown(Write) when you are done sending. Then, read until the stream returns 0. This means that the other side has called Shutdown, too.
Only after you have closed writing (using Shutdown) and received a zero-length read, the communication is really done on the wire. Now Dispose the Socket as it is now defunct.
That way you only get an exception if a network error or a bug occurred. In that case you should probably discard the current "transaction" and restart it.
This error has several causes, butt the most common is that you wrote to a connection that had already been closed by the other end. In other words, an application protocol error: you wrote something in a situation where it could never be consumed.
Another somewhat remote possibility if you wrote both ends is that you coded the client to close abortively for some reason. Basically you should never do that.