*The concepts in this article apply to .NET 1.1 and 3.0 as well, but my links below are for 2.0.
From what I found recently, there are lots of sites that attempt to describe what goes into creating a Telnet session using .NET in general, C# specifically. But not many of them are truly helpful. There are several sites that point you to custom classes, libraries, or even controls that you can download and use blindly. Those leave me feeling like I left the house not wearing any pants.
When you boil down the discussion, it’s really just a Socket to some server on port 23, which is the default port for Telnet. So I’m going to try to describe what needs to happen simply and then point you to the site I used to create my own code. I might even post my own code, but it really is mostly a copy-and-paste job from the MSDN site.
A socket is simply a connection to a server. How data gets passed back and forth is just detail info that only the “founding fathers” care about any more. That statement will probably come back and haunt me some day, hopefully not today. Anyway, that’s about it. Create a socket on port 23 to a specified server, open it, do your business, and close it.
If you’re going to use the System.Net.Sockets class, here’s what you do:
- Create an IPEndpoint, which points to the specified server and port. You can query DNS.GetHostEntry to change a computer name to an IPHostEntry object.
- Create a socket object with the following parameters: AddressFamily.InterNetwork (IP version 4), SocketType.Stream (rides on InterNetwork and Tcp parameters), ProtocolType.Tcp (reliable, two-way connection)
- Open the socket like this: socket.Connect(endpoint); //yup, it’s that simple
- Send your data using socket.Send(… wait, I forgot something. You have to encode the data first so it can fly across them wires.
- Use Encoding.ASCII.GetBytes to convert the nice message you have for the server into bytes.
- Then use socket.Send to send those bytes on their way.
- Listen for a response (one byte at a time, or into a byte array) using socket.Receive
- Don’t forget to clean up by calling socket.Close()
That’s all that’s really required. There are neat little tricks like asynchronous calls which will allow you to send your data and then pick up the response from the local post office when it’s ready (NOT literally, in case you’re gullible). Very cool stuff, but I’m trying to present the “quick and dirty, but correct and simple” solution.
Let’s look at it another way. You can use a System.Net.Sockets.TcpClient object instead of a socket object, which already has the socket parameters configured to use ProtocolType.Tcp. So let’s walk through that option:
- Create a new TcpClient object, which takes a server name and a port (no IPEndPoint necessary, nice).
- Pull a NetworkStream out of the TcpClient by calling GetStream()
- Convert your message into bytes using Encoding.ASCII.GetBytes(string)
- Now you can send and receive data using the stream.Write and stream.Read methods, respectively. The stream.Read method returns the number of bytes written to your receiving array, by the way.
- Put the data back into human-readable format using Encoding.ASCII.GetString(byte array).
- Clean up your mess before the network admins get mad by calling stream.Close() and client.Close().
See, wasn’t that simple? I knew you could do it. Oh, one little note: If you’re trying to log into the machine (first thing, usually), don’t forget to send the next-line character “\n” after your user name and password (one each) so that your credentials are submitted. That darn Socket just plan overlooks the fact that it was supposed to hit Enter for you. Incompetent, I know. But be patient, we’re all friends here.
If any of you need a challenge to get you through the day, here’s one. I was able to connect to one server using this technique but another server passed back a response that appeared to be encoded differently. It had characters like an arrow pointing up and a solid black triangle pointing down. I’m assuming that’s Unicode, but I’m unable to read Unicode and I haven’t figured out how to get .NET to translate it for me. Yes, I’ve tried Convert.ToBase64String and Encoding.*.GetString (BigEndian, UTF7, UTF32, etc). Come on now, I hope I’m smarter than that.