Send data to remote server using Sockets - c#

I want send data to remote server i know its IP address and Port number. Let say it is xxx.xxx.xx.xx and port number is 123. It works with TCP. I want to send first-last name, email, and host name where host name is the new name which i am going to give my machine. Server should give me response in the form of key value as 123-01234. Here I do not understand how i would send data to server using socket. I did work with just simple strings. I have one last more question, Have i need to make server program in it.
public void Connect(String server)
{
Int32 port = 123;
TcpClient client = new TcpClient(server, port);
string FNAME = "reet";
Byte[] data = System.Text.Encoding.ASCII.GetBytes(FNAME);
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", FNAME);
data = new Byte[256];
String responseData = String.Empty;
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", responseData);
stream.Close();
client.Close();
}

To open a socket, you can either use the Socket type, or the TcpClient type (assuming it is TCP). The IP address and port are specified in the constructor for either. Then you need to decide whether you're going to use the Socket API, vs the NetworkStream API, to actually do the communications. If you're using a raw Socket (.Client on a TcpClient), then you use the Send and Receive methods (and the related async options). If you prefer a Stream, then that is .GetStream() on TcpClient, or new NetworkStream(socketInstance) for Socket, and Read / Write. With a Stream, you can of course wrap it in a StreamReader / StreamWriter if you want a simple text API, but it isn't clear whether your socket API is text or binary. You mention wanting to receive 123-01234, but that could be encoded many different ways, so ultimately you need to be very clear about what the socket API expects, at the byte level.

Related

C# Telnet client give none/incomplete output

I have a problem with the basic implementation of telnet client in C#. When I try to connect to the remote computer in local network via command line (telnet 192.168.0.255 23), there are no problems, but with this code, I cannot get for me any logical output
(just chars "??%?? ?? ??'??¬?? ??").
TcpClient telnetClient = new TcpClient("192.168.0.255", 23);
NetworkStream telnetStream = telnetClient.GetStream();
byte[] data = new Byte[4];
string responseData = String.Empty;
int bytes = telnetStream.Read(data, 0, data.Length);
while (true){
responseData += Encoding.ASCII.GetString(data, 0, bytes);
bytes = telnetStream.Read(data, 0, data.Length);
if (!telnetStream.DataAvailable)
break;
}
Console.WriteLine(responseData);
telnetClient.Close();
I realize when I try to get output from different public servers (for example. telehack.com), I get just in some cases first line of output. But output, which is provided via command line is much much extensive.
Telnet connection to remote pc in LAN via telnet and c#
Connection to public pc via telnet and c#
Could you please tell me what I doing terribly wrong? :)
Thank you all for help.
The first bytes send via Telnet in the case of telehack.com are Command bytes (see https://en.wikipedia.org/wiki/Telnet#Telnet_data ). They Start with 0xFF and then the command. You can see them clearly in the example below in the debug window (numbers there are in decimal).
I tried this with your (extended) C# script:

How to implement IPP gateway using C#?

I need to develop a Internet Printing Protocol gateway in .Net that will receive the print jobs fired from IOS using the AirPrint client. The gateway will receive the document fired and release it to the print queue. I am able to broadcast my print services using the SDK provided by Apple. However, when I listen on a port to receive network streams of a document, I am not able to detect the end of stream received as the client keeps on sending streams. My guess is we have to read the attributes and respond accordingly, but I have no idea of these attributes. Below is the code that I am currently using:
IPAddress ipAddress = IPAddress.Parse("10.0.0.13");
IPAddress tcpListener = new TcpListener(ipAddress, 631);
tcpListener.Start();
while (true)
{
TcpClient tcpClient = tcpListener.AcceptTcpClient();
byte[] bytes = new byte[2560];
NetworkStream stream = tcpClient.GetStream();
stream.Read(bytes, 0, bytes.Length);
string mstrMessage = Encoding.ASCII.GetString(bytesReceived, 0, bytesReceived.Length);
string Continue = "HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK\r\nCache-Control: no-cache\r\nDate: " + dateTime + "\r\nPragma: no-cache\r\nTransfer-Encoding: chunked\r\nContent-Type: application/ipp\r\n\r\nattributes-charset utf-8 attributes-natural-language en-us compression-supported none printer-is-accepting-jobs true document-format-supported application/pdf\r\n\r\n0\r\n";
bytesSent = Encoding.ASCII.GetBytes(mstrResponse);
stream.Write(bytesSent, 0, bytesSent.Length);
}
You should check the stream.Read for the returning value.
If it isn't zero you have incoming bytes from the TcpClient:
var bytesLength = 0;
do
{
bytesLength = stream.Read(bytes, 0, bytes.Length);
if (bytesLength == 0) return;
}
while(bytesLength > 0);
You need to understand the level of communication. You're not even reading or writing proper IPP messages yet. 100 continue is purley HTTP related.
Even though Apples Spec for AirPrint is not publicly available there's still a lot of information online. In short: AirPrint is based on IPP. As for the supported PDL PDF is a good choice but not the only one. iOS first checks the printers capabilities. It's up to you what kind of (virtual) print-server you offer.
(In case you have a business case and require a remote developer, don't hestitate to contact us.)

Reading data from a StreamSocket

From looking at the example application on the Microsoft Website How to connect with a stream socket (XAML)
, I have learned how to connect to a server, and send string to the server. However, the example doesn't quite extend on reading data from the socket.
The server is a c# windows console application and what it does is send data to the mobile client by using a network stream.
//send user response
//message is a frame packet containing information
message = new Message();
//type 1 just means it's successfull
message.type = 1;
//using Newton JSON i convert the Message Object into a string object
string sendData = JsonConvert.SerializeObject(message);
//conver the string into a bytearray and store in the variable data (type byte array)
byte[] data = GetBytes(sendData);
//netStream is my NetworkStream i want to write the byte array called data, starting to from 0, and ending at the last point in array
netStream.Write(data, 0, data.Length);
//flushing the stream, not sure why, flushing means to push data
netStream.Flush();
//debugging
Console.WriteLine("sent");
In order to read data from a stream, the DataReader class is used. I am quite new to c# Mobile, and the documentation on the DataReader class doesn't provide any implementations of examples, so how can I read data from the Stream Socket?
Using the example code from microsoft;
DataReader reader = new DataReader(clientSocket.InputStream);
// Set inputstream options so that we don't have to know the data size
reader.InputStreamOptions = InputStreamOptions.Partial;
await reader.LoadAsync(reader.UnconsumedBufferLength);
But now I am not sure how to read the byte array sent from the server.

HttpWebRequest through two proxies

I have recently set up a website which uses geographic DNS to resolve the DNS to two different IP's depending on your location.
However, this means to monitor the websites, I need to make sure the site is available in both geographical locations. To do this I wrote a small program in .net to continually try and HttpWebRequest to get a small html file on the website once using the local internet settings and once using a proxy based in the region which will resolve the name to the second IP address.
This works fine on my laptop at home, however in the office, to connect to the internet on almost all machines you will need to go via a proxy, which means the proxy I set earlier no longer works.
What I need to be able to do is send the request through the office proxy, then through the proxy in the remote country and finally to the website.
Let me know if this is not clear enough!
First you need to ensure that both proxies are HTTPS and they both support CONNECT method, i.e. "proxy chaining". Design of usual HTTP protocol doesn't provide support for "proxy chaining".
The idea is to establish 2 CONNECT tunnels, one inside another.
The algorithm is the following:
Connect to the 1st proxy via TCP
Request CONNECT tunnel to 2nd proxy
Once tunnel is created, request tunnel to target host
Send request. Request will go to target host through proxy #1 and proxy #2.
Below is a sample code which I have tested on my box:
string host = "encrypted.google.com";
string proxy2 = "213.240.237.149";//host;
int proxyPort2 = 3128;//443;
string proxy = "180.183.236.63";//host;
int proxyPort = 3128;//443;
byte[] buffer = new byte[2048];
int bytes;
// Connect to the 1st proxy
TcpClient client = new TcpClient(proxy, proxyPort);
NetworkStream stream = client.GetStream();
// Establish tunnel to 2nd proxy
byte[] tunnelRequest = Encoding.UTF8.GetBytes(String.Format("CONNECT {0}:{1} HTTP/1.1\r\nHost:{0}\r\n\r\n", proxy2, proxyPort2));
stream.Write(tunnelRequest, 0, tunnelRequest.Length);
stream.Flush();
// Read response to CONNECT request
// There should be loop that reads multiple packets
bytes = stream.Read(buffer, 0, buffer.Length);
Console.Write(Encoding.UTF8.GetString(buffer, 0, bytes));
// Establish tunnel to target host
tunnelRequest = Encoding.UTF8.GetBytes(String.Format("CONNECT {0}:443 HTTP/1.1\r\nHost:{0}\r\n\r\n", host));
stream.Write(tunnelRequest, 0, tunnelRequest.Length);
stream.Flush();
// Read response to CONNECT request
// There should be loop that reads multiple packets
bytes = stream.Read(buffer, 0, buffer.Length);
Console.Write(Encoding.UTF8.GetString(buffer, 0, bytes));
// Wrap into SSL stream
SslStream sslStream2 = new SslStream(stream);
sslStream2.AuthenticateAsClient(host);
// Send request
byte[] request = Encoding.UTF8.GetBytes(String.Format("GET https://{0}/ HTTP/1.1\r\nHost: {0}\r\n\r\n", host));
sslStream2.Write(request, 0, request.Length);
sslStream2.Flush();
// Read response
do
{
bytes = sslStream2.Read(buffer, 0, buffer.Length);
Console.Write(Encoding.UTF8.GetString(buffer, 0, bytes));
} while (bytes != 0);
client.Close();
Console.ReadKey();

Sending a image file using a socket in C# (Large Data)

i want to send a large data (image) approx . 1MB file though a socket connection
Question 1
following code snippet of the socket client which i currently use to send a a text message .. how i can modify this to send a file ?
NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(richTextBox1.Text+"$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
Question 2 : What modifications that required in both socket client and server to send and get large files ?
For large data portions you will probably need some kind of transmitting by portions. In your snippet you get all of the data in the array which couldn't be possible if file is large enough (or at least not suitable if it is not just one file to send).
Sending side will be something like that:
const int bufsize = 8192;
var buffer = new byte[bufsize];
NetworkStream ns = socket.GetStream();
using (var s = File.OpenRead("path"))
{
int actuallyRead;
while ((actuallyRead = s.Read(buffer, 0, bufsize)) > 0)
{
ns.Write(buffer, 0, actuallyRead);
}
}
ns.Flush();
Receiving site is just symmetric.
A socket doesn't care if you send text or binary data. Or how much you send. If there's any trouble then it is at the receiving end, code you didn't post. A classic mistake is to forget that a NetworkStream is a stream and not a sequence of packets. The Read() call at the receiving end can return any number of bytes. It won't be the number of bytes you wrote in the Write() call, depending on how routers in between the two machines broke up the IP packets and how much data is buffered in the receiver. You are probably getting away with calling Read only once because the string is short. That is definitely not going to work when you send a lot of data.
You need a protocol to help the receiver figure out when it received all the data. A simple way to do this is by first sending the length of the data. The receiver can then first read that length, then know how long to keep calling Read() to get the rest of the data.
You can arbitrarily extend this protocol by, say, sending the name of the file. Etcetera. Although that by the time you're done, you'd be close to having re-invented FTP.
If all you want to do is to send an image and you don't need any metadata, you can use code like this:
Server:
var listener = new TcpListener(address, port);
listener.Start();
using (var incoming = listener.AcceptTcpClient())
using (var networkStream = incoming.GetStream())
using (var fileStream = File.OpenWrite(imagePath))
{
networkStream.CopyTo(fileStream);
}
listener.Stop();
Client:
var client = new TcpClient();
client.Connect(address, port);
using (var networkStream = client.GetStream())
using (var fileStream = File.OpenRead(imagePath))
{
fileStream.CopyTo(networkStream);
}
client.Close();
If you want to compress the file, you can use GZipStream.
This code uses CopyTo() method, which is available in .Net 4, but you can write it yourself in earlier versions.

Categories