I'm running a server on a linux kernel, which starts listening to a port and then crashes (this is not subject here). When I then try to establish a connection from some client using the following code, it looks as if everything is working: The TcpClient gets connected immediately and the send operation succeeds. However, I obviously will never get a response.
TcpClient tcpClient = new TcpClient();
tcpClient.Connect(new IPEndPoint(new IPAddress(new byte[] { 192,168,0,1 }), 123));
if (tcpClient.Connected)
{
Console.WriteLine("Connected");
client.NoDelay = true;
NetworkStream stream = tcpClient.GetStream();
stream.Write(new byte[] { 0 }, 0, 1);
stream.Flush();
Console.WriteLine("Sent");
}
How can I determine if the connection is actually open? When the client now tries to do send a command and waits for the response, it will block until the timeout.
The actual code is part of a wrapper around TcpClient which should handle the connection, send messages and receive the responses. It has no idea about the underlying protocol (so send anything and wait for a response seems not useful...)
Related
I am using a TcpListener to receive messages. One of our clients is having an issue where the listener occasionally will not reconnect after receiving a message. My reconnect code is pretty basic, and straight from the TcpListener API.
tcpClientConnected = new ManualResetEvent(false);
server = new TcpListener(IPAddress.Any, Port);
server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
server.Start();
while (isListening)
{
Parent.Log("******************** WAITING FOR A MESSAGE ********************", Verbose.Debug);
tcpClientConnected.Reset();
server.BeginAcceptTcpClient(new AsyncCallback(AcceptMessage), server);
tcpClientConnected.WaitOne(); // Wait for an incoming message
if(isListening)
Parent.Log("******************** CONNECTION RESET ********************", Verbose.Debug);
else
Parent.Log("******************** LISTENER DISCONNECTED ********************", Verbose.Debug);
}
Because of logging, I know that tcpClientConnected.Set() gets called. IsListening is still true, and the code loops back to BeginAcceptTcpClient. The first line of code in AcceptMessage writes to the log, and this is never hit. Therefore, I know that a new message is never received, and the server locks.
This customer can run for several days successfully, and then lock up. This is only happening with a single customer.In my AcceptMessage code, I make use of using statements:
TcpListener listener = (TcpListener)ar.AsyncState;
using (TcpClient client = listener.EndAcceptTcpClient(ar))
using (NetworkStream stream = client.GetStream())
I do not reference the listener after creating the client. In this code, I allow for multi-buffer messages, but I don't think anything in there is causing the issue.
My question is, why is BeginAcceptTcpClient not connecting, and is there anything that I can do to detect this and have it try again if needed?
i have few questions about programming a TcpListener.
First problem:
Once client is connected using browser, i see the request. it is all ok. but then i face the problem with writing. and client recieving that data. it basically never gets a reply from server. do i need that flush function ? how does it work ? and is there any others ways of doing it ?
Porblem number 2 which is even more weird. when i call client.close() client doesnt go anywhere. it is still there. browser is stillw ating for data. and when i kill connection in the browser, only then Tcp client gets closed and loop starts again.
namespace TestServer
{
class Program
{
public static void Main()
{
TcpListener server;
IPAddress addr = IPAddress.Parse("127.0.0.1");
server = new TcpListener(addr, 80);
server.Start();
byte[] buffer = new byte[1024];
while(true)
{
string data = null;
Console.WriteLine("Awaiting for connections");
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected...");
NetworkStream str = client.GetStream();
int msgCounter;
while ((msgCounter = str.Read(buffer, 0, buffer.Length)) != 0)
{
Console.WriteLine("Processing stream...");
data += System.Text.Encoding.ASCII.GetString(buffer, 0, msgCounter);
Console.WriteLine("Reciaved: {0}", System.Text.Encoding.ASCII.GetString(buffer, 0, msgCounter));
}
byte[] response = System.Text.Encoding.ASCII.GetBytes("200 OK");
str.Write(response, 0, response.Length);
str.Flush();
client.Close();
buffer = new byte[1024];
}
}
}
}
TCP as a bi-directional transport layer protocol does not denote any concept of the "client is done sending request" signal.
What it means for developers is that such signaling must be defined in the application (or any other higher level) protocol layer.
In your case it is declared by HTTP itself in the https://tools.ietf.org/html//rfc2616#section-5
So if you intend to implement an HTTP server you must parse the HTTP request that has a determined way to identify the end of the request (see the link above).
To summarise: you need to know somehow you've read the request entirely and you may start processing it and generating/sending the response.
I'd recommend you to start with a million times proven working MSDN example of TcpListener class. Additionally I can point to explicit wrong approach:
Do not recreate buffer, it is a waste of resources.
Do not use browser as a test client if you are working with TCP sockets. Any browser tries to correct somehow HTTP protocol errors and can do it in very unpredictable way. If you need HTTP level of debugging, use Fiddler, for lower levels - Microsoft Network Monitor, Wireshark of Netcat.
It could be useful to read some book about TCP/IP networking. Particularly, you will know, that there is not "close" operation or command for TCP connection by protocol definition, TcpClient just emulate it. Instead a peer can send "shutdown" to another one, it does mean it doesn't plan to send data anymore, but can read it. Connection can be considered as closed only after both peers have sent their "shutdown" and received "shutdown" from each other.
So I have a client server model based off of using a TCPClient's stream and turning it into an SSLStream for security purposes, but each time the client wants to send something new to the server, it opens a new TCP connection to the server as the server ends the connection at the end. How would I go about listening for additional requests from the same stream? Not sure how and that's why I'm killing the stream at the end. Sorry if it's confusing, I can revise if not understandable. Thanks!
public void ServerListen()
{
TCPListener Server = new TCPListener(IPAddress.Any, 8001);
while (true)
{
Server.Start();
TCPClient TempClient = Server.AcceptTCPClient();
HandleRequest NewRequest = new HandleRequest(TempClient); // Send to a data handler class and open a separate thread to allow for additional clients to connect
}
}
public class HandleRequest
{
TCPClient WorkingClient;
public HandleRequest(TCPClient TempClient)
{
WorkingClient = TempClient;
(new Thread(new ThreadStart(DoWork))).Start();
}
public static void DoWork()
{
// Do Something Here With Data From Client
ProvideResponse(SomeData);
}
public static void ProvideResponse(object Data)
{
SSLStream SecureStream = new SSLStream(WorkingClient, false); // Kill inner stream after creating a secure connection
SecureStream.AuthenticateAsServer(MyCertificate, false, SslProtocols.Tls, true);
XmlSerializer XS = new XMLSerializer(typeof(someclass));
someclass TempObject = new someclass(){ InnerData = Data};
if (SecureStream.CanWrite)
{
XS.Serialize(SecureStream, TempObject);
}
SecureStream.Close();
}
}
SslStream simply wraps around another Stream. If you call AuthenticateAsServer() the other side should AuthenticateAsClient() and from that point on you can communicate over SSL. If either side fails to call this method, the SslStream will throw an exception.
If you close an SslStream constructed with the leaveInnerStreamOpen parameter set to true, you can then communicate directly over the underlying stream as if there never was an SslStream (and you can even send and receive directly to/from the underlying stream while the SslStream is still open).
In a typical scenario like HTTPS, client and server would enable SSL as soon as the connection is established, and continue using that for the duration of the connection. There's nothing stopping you though from closing the SslStream on both sides after a request/response, and recreating one for the next message - you'd just have to keep the "ssl state" synchronized between client and server.
As for your comment:
Once a TCP connection is established, you can send and receive data for as long as both sides stay connected. For example:
TcpClient client = TcpListener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
while (true)
{
int bytes = stream.Read(...);
if (bytes == 0)
{
// other side has disconnected
stream.Close();
break;
}
// add incoming data to buffer, process messages
...
}
It's like talking to someone by writing text on a piece of paper you show to one another - you simply continue writing on the same piece of paper, and the other side can read while you write.
If you close the TcpClient after a request/response and open a new one using TcpListener.AcceptXxx(), you're throwing away each piece of paper after every message.
If I were you I'd play with these concepts (using the NetworkStream class) without the SslStream wrapper, until you feel you're doing the right thing. The SslStream layer can be added without any significant changes to code that uses NetworkStream.
I wrote simple application that using TcpListener.
The application is wait till some client will connect - and while the client is connected the application will listen to his sending stream.
In the code - i using while loop to check if the client is connected.
But event when i close the connection on the client side i get connected == true
But .. on the client close => i see that the server get byte stream with byte.length == 0
Code ...
private async void button1_Click(object sender, EventArgs e)
{
TcpListener tcpListener = new TcpListener(IPAddress.Any, 5501);
tcpListener.Start(1); // listen one client only
TcpClient client = await tcpListener.AcceptTcpClientAsync();
NetworkStream networkStream = client.GetStream();
while (client.Connected) // after connected => this is always true .. event if i close the connection on the client side
{
// do something ...
}
System.Console.WriteLine("No Connected");
}
TCP is a connection-oriented protocol, but the connection still is a virtual one - the only way to know that the other party is still connected is by successfully sending or receiving a message to/from it. This is why the Connected property may give false positives.
The 0-byte message means that the client has sent all their data and has closed (the send direction of) the socket. At that point the client still is connected, waiting for a 0-byte message back from the server (which is automatically sent when you close the server socket).
Of course in case of a network failure you would never receive that 0-byte message, but you would receive (eventually) a SocketException instead.
See this WinSock FAQ for more information about the shutdown process.
I am trying to write a basic app that will read data off a port. Here is my code:
static void Main(string[] args)
{
int port = 5600;
string server = "MyDevLaptopName";
TcpClient tcpClient = new TcpClient();
tcpClient.Connect(server, port);
NetworkStream stream = tcpClient.GetStream();
byte[] data = new byte[256];
stream.Read(data, 0, data.Length);
Console.ReadLine();
}
When I run the app above I get this error on the tcpClient.Connect command:
A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 10.90.91.19:5600
I am not sure why my computer will not respond (I am totally new to TCP ports and such).
Is there a different way I need set this up to read data from a TCP port?
Things I have checked:
Windows Firewall is completely off.
The IP address listed in the error is the internal IP address of my development machine (the machine I am trying to connect to).
I do have Symantec Endpoint Protection, but it is controlled by Group Policy and it would be difficult for me to get turned off (but I can do it if need be).
Update:
There is a main frame server that is supposed to be sending TCP data to that port. I do not control that machine/server or the method that it sends the data. I am just trying to read the data that is sent to the port.
Update II:
The main frame is actually sending the data to a VM at my company. I then use the technique found here to redirect that TCP traffic to the same port on my machine (where I hoped I could just read it off).
Update III:
The mainframe is the client and I need to be the server!. Once I realized that I got things working.
I would try with another port number, are you in control of the server as well? if so try to follow these steps:
C# Tutorial - Simple Threaded TCP Server
as you will see there you can listen in this way:
namespace TCPServerTutorial
{
class Server
{
private TcpListener tcpListener;
private Thread listenThread;
public Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
}
}
and you can connect in this way:
TcpClient client = new TcpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);
client.Connect(serverEndPoint);
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Server!");
clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();
it seems trivial and it is, but port number is not a detail as some ports are not available or blocked by firewalls or so...
Your code is the "client." You need a "server" running on the other machine that is listening for your incoming connection.