Send TCP type message using WCF - c#

I am trying to send a tcp message to a gprs server. I was trying to do it through WCF, however, I always see tutorials or information regarding the consumption of services, however, there is no service to consume. It is simply sending a tcp-type message to a server using WCF. I have the port, and the server for the connection. How could I do it? I need to create the WCF client for sending messages, but I don't know how without services.
I am using visual studio and c # language

I am trying to send a tcp message to a gprs server. I was trying to do it through WCF
Since the remote server is not a SOAP service but simply a server exposing a TCP port you should use TCP APIs rather than WCF. The reason being that message content and protocol will be different. WCF uses SOAP messages which generally are sent as XML text as opposed to TCP which is binary. Now you could configure WCF to serialize as binary but the result will still be different. There are alot more differences to TCP vs WCF which I won't go into here.
Use the following TCP example:
TcpClient client = new TcpClient("localhost", 80); //enter your server ip and port
// Translate the passed message into ASCII and store it as a Byte array
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
// Get the stream for writing
NetworkStream stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
//Close everything to avoid memory leaks
stream.Close();
client.Close();

Related

HTTP request over GPRS and TCP dropping packets

I'm writing a server for a biometric fingerprint device that connects via GPRS. The server receives GET and POST requests from the device and then will perform the required actions.
With the POST requests, the device should attach some additional data to the request.
The problem is, when I connect the device to the server via LAN, all the data comes through fine. When I connect via GPRS, the request body doesn't get picked up by my server.
On the left, is when I connect via LAN...the body of the message is attached. On the right, is via GPRS, everything remains the same, however, there is no body.
I ran Wireshark over the LAN and the GPRS connections. The packets, when I drill down, all have the body attached but on Wireshark, over GPRS, I get messages like above - with the out of order and RST, ACK and sometime PSH, ACK.
Contrasted with the LAN packets, which have none of these problems.
This is the code I'm using to read from the TCPListener
try
{
if (tcp == null)
{
this.tcp = new TcpListener(IPAddress.Parse(serverIP), port);
}
this.tcp.Start();
listening = true;
while (listening)
{
Socket mySocket = null;
// Blocks until a client has connected to the server
try
{
mySocket = this.tcp.AcceptSocket();
Thread.Sleep(500);
byte[] bReceive = new byte[1024 * 1024 * 2];
mySocket.Receive(bReceive);
Analysis(bReceive, mySocket);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
this.tcp.Stop();
This is the original code I got from their developer. I've tried various combinations of async, TcpClient and different socket options such as KeepAlive and DontLinger, but none seem to cure this problem.
Other than manually capturing the packets in C# to get the body, are there any C# classes I can use to read the entire request?
TCP is a stream oriented protocol. Everybody knows that but a lot of developers do not consider that when they implement a TCP receiver.
When a send calls Send("ABCDEFG") and client calls Receive(buffer) the buffer may contain "ABCDEFG" or "ABCD" or "A" or whatever substring from original data that begins with "A". TCP is a stream of data without any information about message boundaries.
The receiver that needs to receive a message with a length that is unknown during the compile time (like an HTTP request) must contain a logic that receives the header, parse it and than waits till complete message is received.
But you don't need to implement it yourself. C# has the class HttpServer that already contains this logic. Moreover there are libraries with REST support. It is reinventing wheel to implement a REST server and start with TcpListener and sockets.
I ended up implementing the server as async using the code in the link below. This is so I could implement the logic to reread the stream if the end of the stream hasn't been reached. I just had to change the end of file condition for my circumstances.
Here's a link to the article:
https://learn.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-server-socket-example

C# Socket Programming, How can you choose which client to connect to from the server client?

Im making a program in c#, the server side program listens to a port and the client connect to the server. But I want to pick which client to connect to when all the clients are trying to connect.
Each connection that's made to your server gives you a reference to a Socket object that you can use for sending data back or serving your clients, e.g.:
Socket handler = listener.Accept()
// ...
// do your processing
// ...
byte[] msg = Encoding.ASCII.GetBytes("Sending response to client");
handler.Send(msg);
Don't lose the reference to that Socket object.

Transparent proxy - from port 80 to 443

I'm trying to develop a transparent proxy which forwards unsecured http traffic from the clients as secured https traffic to the server, and back again. To better illustrate my point, take a look at the following image.
Let's suppose that for various reasons the clients will be using HTTP only, they can't use port 443 for HTTPS. Since some servers don't accept traffic from port 80, my proxy needs to reroute them to port 443. This is a possible scenario:
Receive data from client which are headed to port 80 towards www.google.com
Initialize connection with https://www.google.com to port 443 (Do the handshake and so on)
Encrypt data from client and send them to https://www.google.com to port 443.
Receive response from https://www.google.com, decrypt them and send them back to the client to port 80.
Since this is a transparent proxy, the clients (in my case lots of them) shouldn't need any extra configuration. The network is already configured so that their traffic go through my node. Currently my node simply reroutes the data and blocks some if they contain viruses. This is done using WinPcap to get access to low networking layers but I'm willing to change my approach if it's too hard to be done using raw packets (mainly concerned about the handshake).
What I've tried:
Note: www.google.com could be any site on the web. It's merely used as an example.
Iridium's suggestion. This doesn't work for the reason that TcpListener only accepts a new connection if another application uses a TcpClient to connect to it. Since this is a transparent proxy, it doesn't work.
Using HttpListener instead. However, it seems that this doesn't work since it only accepts connections to my own IP (not www.google.com).
Using HttpListener as before but this time I'm forwarding packets to my own IP so that HttpListener accepts the connection. For some reason, this doesn't seem to work (Inspected through wireshark and TCP SYN packets keep re-sending, not sure why or how to fix it).
Using SslStream to connect to https://www.google.com, then getting the contents from the raw packets received from the clients and writing them to the stream. This doesn't work since SslStream handles TCP packets (Such as ACK or SYN) on its own. The stream expects only Http requests. Another reason why it doesn't work is because I can't read the contents of TCP packets from the stream, only the contents of HTTP responses (So the client is sat there waiting for an ACK).
Forwarding TCP packets from the client as they are to port 443 and from the server to port 80 (Since only HTTP requests and responses are encrypted with SSL, it wouldn't make a difference) and using the HttpRequest class to make all the http requests and responses (Since the class handles the handshake on its own). This doesn't work because the ACKs are wrong on both sides.
What would be the best way to go into developing such a proxy?
Edit: Is there ANY way that TcpListener or HttpListener can act as a transparent proxy? (Without configuration on the clients' computers). When exactly does HttpListener recognize that a client is trying to connect?
I don't really understand why you need to read the encrypted data from the SslStream. If I'm reading your description correctly, you should simply need to:
Wait for a client connection
When a client connects, connect to the server
Wrap the server connection's NetworkStream in an SslStream and AuthenticateAsClient
Once authenticated, in parallel:
Read data from the client and write it to the SslStream
Read data from the SslStream and write it to the client
I don't see anywhere in this process that you'd need to see the encrypted data from the SslStream.
The following is a very basic sample (though completely untested):
static void Main(string[] args)
{
var listener = new TcpListener(IPAddress.Any, 11180);
var clientConnection = listener.AcceptTcpClient();
// When we get here, the client has connected, initiate the server connection
var serverConnection = new TcpClient("your.server.name", 443);
var serverStream = serverConnection.GetStream();
var secureStream = new SslStream(serverStream);
secureStream.AuthenticateAsClient("your.server.name");
ConnectStreams(clientConnection.GetStream(), secureStream);
}
private static void ConnectStreams(Stream streamA, Stream streamB)
{
ForwardStream(streamA, streamB, new byte[1024]);
ForwardStream(streamB, streamA, new byte[1024]);
}
private static void ForwardStream(Stream source, Stream destination, byte[] buffer)
{
source.BeginRead(buffer, 0, buffer.Length, r => Forward(source, destination, r, buffer), null);
}
private static void Forward(Stream source, Stream destination, IAsyncResult asyncResult, byte[] buffer)
{
var bytesRead = source.EndRead(asyncResult);
if (bytesRead == 0)
{
destination.Close();
return;
}
destination.Write(buffer, 0, bytesRead);
ForwardStream(source, destination, buffer);
}

Sending a file to a Dynamic port by a TCP Protocol

I am working with an application that receives a file by a TCP protocol, the application processes the file and then sends it by the same protocol, i am receiving the file without problems, my problem is when i try to send the file, because i need to send the file to another application that is listening a Dynamic port, the code that i am using to send these files is:
internal void Send(byte[] buffer)
{
TcpClient _client = null;
try
{
_client = new TcpClient(RemoteIPaddress, Dynamic_port);
if (_client != null)
{
NetworkStream _clienttStream = _client.GetStream();
_clienttStream.Write(buffer, 0, buffer.Length);
_clienttStream.Flush();
_clienttStream.Close();
_clienttStream = null;
}
}
catch
{
if (_client != null)
{
_client.Close();
_client = null;
}
}
}
The question is, how can i send a file by TCP protocol to a remote machine that uses a dynamic port
Typically, the server should listen on a well known port for a connection request. The response should include the port number that the server will communicate further on. Then your app connects to that port for transferring the data.
The communication should do the following:
Client connects to server on well known port.
Server responds with the dynamic port number to use for further communication.
Client connects to server on the received port number.
Server responds stating connection established.
Client transmits data and disconnects.
This is a simplified version of how passive FTP works.
Point is, there are only two ways to connect to a server on a dynamic port. The first way is outlined above. If you can't do it that way then your client app will have to do a port scan, sending a connection attempt to every port within a range, and see which one the server responds on. However, firewalls are generally programmed to notice this type of thing and shut you down (it's hacker behavior).
Are you asking how you can determine the dynamic port that the remote machine has selected to use? There is no automated way to do this. The server should either work on a port that both machines are aware of or you should work out a way for them to select a port through some other mode of communication. Either by connecting to a 3rd party server or hosting a web service that the client can access.

C# - WireShark detects incomming packets but application does not receive them

I've got a strange problem. I have a client sending packets to my server, but my servers UDP socket never receives them. Same thing happens the other way around, if I send and he tries to receive.
Check this image, captured from wireshark:
http://img263.imageshack.us/img263/2636/bokus.png
I hav bound my UDP socket to EndPoint 192.168.2.3, which is the internal IP of the server, and port 9998.
The client sends data to my IP, which should then be forwarded to the local server machine..
As you can see wireshark clearly detects incomming packets for 192.168.2.3 with destination port 9998 but nothing gets delivered!
(...why does it say distinct32 btw in destination port?)
Something else to watch for is make sure any firewall you might running has a rule setup to allow communications on your port 9998.
If I had to guess (would need to see your recieving C# code to know), It looks like you might be trying to receive UDP packets but using TCP protocol on the client side. (Or i might just be misunderstanding some of the text of your screenshot.)
Theres no need to 'listen' for a connection when using UDP. UDP packets don't have a connect/disconnect protocol. Nor do they guarantee that packets are received in the same order they're sent.
try using something along these lines in your C# client and see if you get data.
var udpClient = new System.Net.Sockets.UdpClient(9998);
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);

Categories