I am developing an Tcp client in C# and I am using the TcpClient class.
I am not able to connect to the server.
Debugging the application I can see that the call to Connect is successfull but after I do this , I check with netstat the status of the connection on both server and client. The result is that the server the connection is ESTABLISHED, but on the client I cannot see any connection to the server in netstat result.
Reading the TcpClient instance I can see that the property Connected is true so it should be fine but when I try to read from the NetworkStream it hangs.
When I say it hangs I mean that the server is sending data but the readline doesn't get any data at all.
Do you know what could be the issue and some workaround?
Thanks
First, a recommendation: In my experience, TcpClient is best used asynchronously.
In all my usage of TcpClient though, I've never been able to Read a response without first doing a Write with a request. You'll block forever attempting to synchronously await a response to a request you haven't sent.
Expanding on that, sending a request will be done like this:
TcpClient.GetStream().BeginWrite( tcpMessage, ... );
Which will send the request that's in tcpMessage, which will be a bytestream produced from a string like this:
byte[] tcpMessage = httpEncoding.GetBytes( httpMessage );
Which has your request message like this:
httpMessage = "GET / HTTP/1.1\r\n" + ...;
That sends your request, which causes the server to generate a response which you can then collect like this:
TcpClient.GetStream().BeginRead( ... );
And you should finally be able to receive something back!
Even if it's only a "I didn't like your request!" response. 8 D
What you saw is absolutely normal.
Reading the TcpClient instance I can see that the property Connected is true so it should be fine but when I try to read from the NetworkStream it hangs.
When you try to read, the thread will be blocked till the server sends you some data. Otherwise, based on the read method you used, it can be blocked forever.
It depends on the server, but most TCP servers will wait for the client to send a request before it sends a response. It sounds like your thread is waiting for data. Did you set a read timeout?
Make sure you send a request so that the server knows to send you a response.
Normally, you would put your TcpClient into a separate thread and use a read time out to avoid hanging the whole program awaiting a response.
Make sure that you don't use non-blocking (asynchronous) sockets when communicating with a blocking (synchronous) server, you'll only run into problems. Blocking sockets are normal for the web, as most web services use the request/response paradigm.
on client side, what port were you looking for when you did netstat?
Because when client make connections, it would use ephemeral port. Which means it would use any free port # above maximum of well known port number. So, your client maybe using different port # than you are expecting.
And for the networkstream issue, I would have to see the code to determine what went wrong.
Related
I have a problem with sockets. This:
When client-thread ends, server trying to read, and its freezes, because socket is not closed. Thread dont close it, when its over. Its problem exist, if i using thread, but if i using two independents projects, i have no problem (exception throws, and i can catch it).
I cant use timeout, and i must correct continue server-work, when client dont close socket.
Sorry for my bad eng.
As far as I know, there is no way for TCP server (listener) to find out whether data from client are not coming because it has died/quit or is just inactive. This is not .NET's defficiency, it is how TCP works. The way I deal with it is:
1. Create a timer in my client that periodically sends signal "I am alive" to the server. For example, I just send 1 unusual ASCII character '∩' (code 239).
2. In TCP listener: use NetworkStream.Read(...) method that allows to specify timeout. If timeout expires, the server disposes the old NetworkStream instance and creates new one on the same TCP port. If the server receives "I am alive" signal from client, it keeps listening.
By the way, the property TcpClient.Connected is useless for detecting on server side whether client still uses the socket. The method only returns true if last Read action returned something. So, if client is alive and just silent, the TcpClient.Connected becomes false.
Close client when you want the connection to be closed (at the end of Client).
Better yet, use using for all disposable resources such as both clients and the listener.
I am using TCPCLient and TcpListenersockets. Here am sending request on port 19000 to 192.168.7.56 IP machine. After giving response from that machine i need to response that i got msg to that machine on port 20000.
Means i want to use one port for all requests and another port for response purpose. Is this possible in C#? Is my scenario correct?
Why this requirement is... In TcpListener socket I am getting continues requests from other machine. So it must be always available to get those requests....
After getting request on TcpListener I need to response them that I got req like aknowledgement on different port.
Please suggest how to implement this scenario?
Thanks,
Syed Chand Basha
well the common pattern is
one port and behind a pool for processing request (here you can verify the load the server or maximum clients for processing..etc)
when request enter the pool will create an new thread for process that request
while the main pool can still listening request
also exist other thread monitor the threads for timeout or errors so it can kill process for errors or timeout o long processing
regards
I am trying to write a c# server/client that will simultaneously send byte arrays over TCP across each other. I'm trying to wrap my head around how to accomplish this. All of the example I have seen wait for a message, then send a response. I need communication to happen simultaneously.
Would I need to create 2 separate TCP socket connections for ingoing & outgoing on both the server & client? Can I pass data simultaneously with 1 connection in a "full duplex" fashion? Any help is appreciated.
I would advise you to look at the asynchronous sockets. The reason is, that they don't block threads while receiving or sending data.
Socket.BeginReceive(buffer, offset, size, endReceiveMethod);
The endreceive method will be called when there are bytes received. (on a other thread)
This is the same for sending.
Socket.BeginSend(buffer, offset, size, endSendMethod);
I remember in the early days I was worried about reading and writing on the same thread, creating difficult constructions with read-timeouts etc and each client it's own thread.
This isn't needed with Asynchronous sockets. It doesn't use a single thread per client. It uses I/O Completion Ports http://msdn.microsoft.com/en-us/library/windows/desktop/aa365198(v=vs.85).aspx instead of blocking threads.
You should look into using select() method to listen on server and client file descriptor (or fd). http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.select.aspx
Basically, if you have a TCP server, let us say, fd0 and if the client sends a connect, then the server fd would create a new fd for the new connection, let us call it fd1. Now, you would want to do three things with these: (a) listen for newer incoming connections on fd0, (b) wait for reciving data on fd1, and (c) send data on fd1. Sending data is usually non-blocking, so you dont have to worry about that. But, for (a) and (b), you can use a select.. If there is data to be read on fd1, then you would get a read event. Likewise, if there is a new connection on fd0, then also you would get a read event and you can call accept.
I run my application on a network and in some cases the client lost connection to the server. After this time, when I wanted to send a message to the server I receive the following error: Operation not allowed on non-connected sockets (something like this).
I thought to create an event for object type TcpClient and when tcp_obj.Connected = false to call a function to discontinue execution of the current code. How could I do this?
Or giving me other suggestios.
Thanks.
I know at least from socket programming in Java that when a client loses connection to the server, the server does not and can not know about it. You need a heartbeat of some sort to detect the early disconnection.
We often use a heartbeat in our client/server applications to detect early disconnections and log them on the server. This way the server can close the associated socket and release the connection back to the pool.
Simply send a command to the client periodically and wait for a response. If no response is garnered within a timeout assume disconnect and close streams.
I would simply first check your connection object to ensure you are connected, prior to attempting to send the message. Also make sure that you are putting your send-logic inside of a try-catch, so that if you do happen to get disconnected mid transmission, you'll be able to resume without blowing your application apart.
Psuedo-Code:
private void SendMessage(string message, Socket socket)
{
if(socket.connectionState = States.Connected)
{
try{
// Attempt to Send
}
catch(SocketException Ex)
{
// Disconenct, Additional Cleanup Etc.
}
}
}
If you are in C#, prior to your connection state changing, you will have a socket disconnected event fire, prior to your connection state changing. Make sure you tie this event up as soon as your socket connects.
Can we know why you use TCP sockets? Is for calling a tcp device o server code?
I recommend you if is for calling a .net server app use Windows Communication Foudation. It is simple to expose services by net.tcp, http, etc.
Regards,
Actually this is a very old problem,
If I understand your question correctly you need a way to know whether you're application is still connected to the server or vice versa.
If so then a workaround is to have a UDP connection just to check the connectivity (overhead I know, but its much better then polling on Connected state), you could check just before you send you're data.
Since UDP is not Connection oriented you don't need to be connected when you send the data
Despite the documentation, NetworkStream.Write does not appear to wait until the data has been sent. Instead, it waits until the data has been copied to a buffer and then returns. That buffer is transmitted in the background.
This is the code I have at the moment. Whether I use ns.Write or ns.BeginWrite doesn't matter - both return immediately. The EndWrite also returns immediately (which makes sense since it is writing to the send buffer, not writing to the network).
bool done;
void SendData(TcpClient tcp, byte[] data)
{
NetworkStream ns = tcp.GetStream();
done = false;
ns.BeginWrite(bytWriteBuffer, 0, data.Length, myWriteCallBack, ns);
while (done == false) Thread.Sleep(10);
}
public void myWriteCallBack(IAsyncResult ar)
{
NetworkStream ns = (NetworkStream)ar.AsyncState;
ns.EndWrite(ar);
done = true;
}
How can I tell when the data has actually been sent to the client?
I want to wait for 10 seconds(for example) for a response from the server after sending my data otherwise I'll assume something was wrong. If it takes 15 seconds to send my data, then it will always timeout since I can only start counting from when NetworkStream.Write returns - which is before the data has been sent. I want to start counting 10 seconds from when the data has left my network card.
The amount of data and the time to send it could vary - it could take 1 second to send it, it could take 10 seconds to send it, it could take a minute to send it. The server does send an response when it has received the data (it's a smtp server), but I don't want to wait forever if my data was malformed and the response will never come, which is why I need to know if I'm waiting for the data to be sent, or if I'm waiting for the server to respond.
I might want to show the status to the user - I'd like to show "sending data to server", and "waiting for response from server" - how could I do that?
I'm not a C# programmer, but the way you've asked this question is slightly misleading. The only way to know when your data has been "received", for any useful definition of "received", is to have a specific acknowledgment message in your protocol which indicates the data has been fully processed.
The data does not "leave" your network card, exactly. The best way to think of your program's relationship to the network is:
your program -> lots of confusing stuff -> the peer program
A list of things that might be in the "lots of confusing stuff":
the CLR
the operating system kernel
a virtualized network interface
a switch
a software firewall
a hardware firewall
a router performing network address translation
a router on the peer's end performing network address translation
So, if you are on a virtual machine, which is hosted under a different operating system, that has a software firewall which is controlling the virtual machine's network behavior - when has the data "really" left your network card? Even in the best case scenario, many of these components may drop a packet, which your network card will need to re-transmit. Has it "left" your network card when the first (unsuccessful) attempt has been made? Most networking APIs would say no, it hasn't been "sent" until the other end has sent a TCP acknowledgement.
That said, the documentation for NetworkStream.Write seems to indicate that it will not return until it has at least initiated the 'send' operation:
The Write method blocks until the requested number of bytes is sent or a SocketException is thrown.
Of course, "is sent" is somewhat vague for the reasons I gave above. There's also the possibility that the data will be "really" sent by your program and received by the peer program, but the peer will crash or otherwise not actually process the data. So you should do a Write followed by a Read of a message that will only be emitted by your peer when it has actually processed the message.
TCP is a "reliable" protocol, which means the data will be received at the other end if there are no socket errors. I have seen numerous efforts at second-guessing TCP with a higher level application confirmation, but IMHO this is usually a waste of time and bandwidth.
Typically the problem you describe is handled through normal client/server design, which in its simplest form goes like this...
The client sends a request to the server and does a blocking read on the socket waiting for some kind of response. If there is a problem with the TCP connection then that read will abort. The client should also use a timeout to detect any non-network related issue with the server. If the request fails or times out then the client can retry, report an error, etc.
Once the server has processed the request and sent the response it usually no longer cares what happens - even if the socket goes away during the transaction - because it is up to the client to initiate any further interaction. Personally, I find it very comforting to be the server. :-)
In general, I would recommend sending an acknowledgment from the client anyway. That way you can be 100% sure the data was received, and received correctly.
If I had to guess, the NetworkStream considers the data to have been sent once it hands the buffer off to the Windows Socket. So, I'm not sure there's a way to accomplish what you want via TcpClient.
I can not think of a scenario where NetworkStream.Write wouldn't send the data to the server as soon as possible. Barring massive network congestion or disconnection, it should end up on the other end within a reasonable time. Is it possible that you have a protocol issue? For instance, with HTTP the request headers must end with a blank line, and the server will not send any response until one occurs -- does the protocol in use have a similar end-of-message characteristic?
Here's some cleaner code than your original version, removing the delegate, field, and Thread.Sleep. It preforms the exact same way functionally.
void SendData(TcpClient tcp, byte[] data) {
NetworkStream ns = tcp.GetStream();
// BUG?: should bytWriteBuffer == data?
IAsyncResult r = ns.BeginWrite(bytWriteBuffer, 0, data.Length, null, null);
r.AsyncWaitHandle.WaitOne();
ns.EndWrite(r);
}
Looks like the question was modified while I wrote the above. The .WaitOne() may help your timeout issue. It can be passed a timeout parameter. This is a lazy wait -- the thread will not be scheduled again until the result is finished, or the timeout expires.
I try to understand the intent of .NET NetworkStream designers, and they must design it this way. After Write, the data to send are no longer handled by .NET. Therefore, it is reasonable that Write returns immediately (and the data will be sent out from NIC some time soon).
So in your application design, you should follow this pattern other than trying to make it working your way. For example, use a longer time out before received any data from the NetworkStream can compensate the time consumed before your command leaving the NIC.
In all, it is bad practice to hard code a timeout value inside source files. If the timeout value is configurable at runtime, everything should work fine.
How about using the Flush() method.
ns.Flush()
That should ensure the data is written before continuing.
Bellow .net is windows sockets which use TCP.
TCP uses ACK packets to notify the sender the data has been transferred successfully.
So the sender machine knows when data has been transferred but there is no way (that I am aware of) to get that information in .net.
edit:
Just an idea, never tried:
Write() blocks only if sockets buffer is full. So if we lower that buffers size (SendBufferSize) to a very low value (8? 1? 0?) we may get what we want :)
Perhaps try setting
tcp.NoDelay = true