My application has many tcpclients that is uses to update hundreds of servers when instructed. I'm having trouble in the design with a minor but important issue.
My programs takes an outgoing message out of a queue and selects an available client from an array of clients, I'll call this client1. It starts a connection on the tcpclient with a BeginConnect and issues a call back method. The program then moves on to other messages from the queue and the tcpclients that will be sending them.
When the the callback happens for client1, my program gets an AsyncResult from which I can resolve the socket.
Here is my problem. How do I know which socket or TCPClient I have? It's important because I need to know which message to send on this connected client.
I've looked on the socket and didn't find a name property.
How do I identify the socket so I know the correct messaging conversation to have?
Thanks!
After more study and research I realized the callback would pass any System.Object. So the answer is as simple as wrapping the TCPClient in a class that has properties that can identify it's purpose.
In my case a simple class with a Socket, String for the message, string for the IP, and an int for the Port was enough to handle the situate when it made it to the call back. Just remember you have to cast the IAsyncResult.AsyncState back to the type of your wrapper class.
Related
Basically the title... I'd like to have same feedback on weather NamedPipeServerStream object successfully received a value. This is the starting code:
static void Main(string[] args){
Console.WriteLine("Client running!");
NamedPipeClientStream npc = new NamedPipeClientStream("somename");
npc.Connect();
// npc.WriteTimeout = 1000; does not work, says it is not supported for this stream
byte[] message = Encoding.UTF8.GetBytes("Message");
npc.Write(message);
int response = npc.ReadByte();
Console.WriteLine("response; "+response);
}
I've implemented a small echo message from the NamedPipeServerStream on every read. I imagine I could add some async timeout to check if npc.ReadByte(); did return a value in lets say 200ms. Similar to how TCP packets are ACKed.
Is there a better way of inspecting if namedPipeClientStream.Write() was successful?
I'd like to have same feedback on weather NamedPipeServerStream object successfully received a value
The only way to know for sure that the data you sent was received and successfully processed by the client at the remote endpoint, is for your own application protocol to include such acknowledgements.
As a general rule, you can assume that if your send operations are completing successfully, the connection remains viable and the remote endpoint is getting the data. If something happens to the connection, you'll eventually get an error while sending data.
However, this assumption only goes so far. Network I/O is buffered, usually at several levels. Any of your send operations almost certainly involve doing nothing more than placing the data in a local buffer for the network layer. The method call for the operation will return as soon as the data has been buffered, without regard for whether the remote endpoint has received it (and in fact, almost never will have by the time your call returns).
So if and when such a call throws an exception or otherwise reports an error, it's entirely possible that some of the previously sent data has also been lost in transit.
How best to address this possibility depends on what you're trying to do. But in general, you should not worry about it at all. It will typically not matter if a specific transmission has been received. As long as you can continue transmitting without error, the connection is fine, and asking for acknowledgement is just unnecessary overhead.
If you want to handle the case where an error occurs, invalidating the connection, forcing you to retry, and you want to make the broader operation resumable (e.g. you're streaming some data to the remote endpoint and want to ensure all of the data has been received, without having to resend data that has already been received), then you should build into your application protocol the ability to resume, where on reconnecting the remote endpoint reports the number of bytes it's received so far, or the most recent message ID, or whatever it is your application protocol would need to understand where it needs to start sending again.
See also this very closely-related question (arguably maybe even an actual duplicate…though it doesn't mention named pipes specifically, pretty much all network I/O will involve similar issues):
Does TcpClient write method guarantees the data are delivered to server?
There's a good answer there, as well as links to even more useful Q&A in that answer.
I have a server and client listening with a while loop to process packets sent to each other.
But there are some functions on the client that I would like to send a packet and process the reply on the same function without having to receive the command on its while loop.
Example:
private static string GetMyEmailFromServer() => SendAndGetPacket("GetMyEmail");
The example above sends a packet to the server with the string "GetMyEmail" and waits until it receives a message back then returns the value. The function "SendAndGetPacket" is using an already existing connection to the server to make the request.
As of right now, I have been creating a secondary connection to the server on another port (instead of using the already open and auth connection). I considered creating a whole framework to manage the receiving packets into different channels, where just 1 of the channels are processed in the "while loop" in the client, but I would like to know if there is a high level command for it in C#. Also, if you have a better idea than channels or a guide to implementing an effective channel system, I would appreciate a link or book (doesn't have to be language specified).
Haribol
I have a TcpClient object which can connect to a foreign program. I can send one message (xml serialized message). But as soon as I close my network stream my TcpClient closes and disposes. And the second time I try to send a message via my TcpClient I get an error "cannot access a disposed object, Net.Sockets.Socket".
I am new to using TcpClient but I was under the impression I would connect once with the other program then be able to pass messages back and forth for the lifetime of my program and simply disconnect the TcpClient before closing my program.
The only way I've been able to send multiple messages is if I new the TcpClient, and perform the connect again prior to sending my message. Is this the correct way of sending multiple messages and my manager and I are simply under the wrong impression of TcpClient?
Another impression I had regarding TcpClient was that once connected I'd be able to receive messages from the other program. So my program would be sitting there doing nothing then receive a TcpClient message (some defined xml message) stating inventory has been changed. Is this possible or do I need to set up a TcpListener for that type of functionality to work?
Please don't let this example confuse you or the issue I'm just trying to get my impression across in a different way.
An example of what my impression was is a phone conversation. The TcpClient is the phone and I make a connection by calling another phone number. I would then be connected and be able to talk back and forth. There may be pauses of several minutes before one of us starts the conversation back up again. Then at the end of the work day would hang up the phone.
But after working with TcpClient for a while I'm getting the impression that it's a walkie-talkie conversation. I connect via TcpClient which is my pressing the walkie-talkie button. I talk, and the closing of the network stream is me releasing the button. I can hear back from the person on the other side of the conversation but as soon as I press the button again it changes frequency and it's an entirely new conversation requiring me to new the tcpClient.
EDIT
Everyone that said not to close the stream was right. The reason I kept closing the stream was because the receiver software would then process my message. But the receiving software was also looking for a message to be wrapped in the ASCII STX and ETX characters. If I wrapped my message, sent it along and lo and behold they started processing the message with my stream still open.
Everyone that said not to close the stream was right.
The reason I kept closing the stream was because the receiving software would then process my message. But the receiving software would also process my message if it was wrapped in the ASCII "STX" and "ETX" characters.
My ultimate problem was a little bit of ignorance on TcpClient and a little ignorance on the receiving software's protocols.
I have basically implemented this asynchronous server socket example (and the corresponding client). Using it, I can respond to the client if I follow the example exactly, i.e., if the call to Send() the response is in the ReadCallback() method.
If, however, I try and send a response outside of here, i.e., in a callback that I've attached to my message processing routine (running in a different thread), I get this error, saying the Socket is not connected. If I try and send a response somewhere else in the Server code, say in the while(true) loop that's listening to incoming connections, I get the same error.
Am I missing something fundamental here?
Edit:
Ok, so I read Two-way communication in socket programming using C, and I now think, according to that answer, that I have to modify the example I linked to so that I reply to the server on the socket returned by the accept process. My goal is to be able to call Send() outside of the receive callback, say from Main(), after the client and server are connected.
Please can someone suggest how I modify the example to achieve what I want? I'm getting thoroughly confused about this, and don't want to create a separate stream if I don't need to (which according to the question I posted, I don't need to...).
If you want to keep the connection open then would need to persist the handler variable as that is the open socket connection. Then whenever you want to send that connection a message you retrieve its socket and send.
Also, you obviously wouldn't call Shutdown() and Close() on the handler variable.
I've just started learning Sockets through various Google searches but I'm having some problems figuring it out how to properly use Sockets in C# and I'm in the need of some help.
I have a test application (Windows Forms) and on a different class (which is actually in it's own .dll, but that's irrelevant) I have all the server/client code for my sockets code.
Question 1)
On my test application, on the server part, the user can click the "start listening" button and the server part of my sockets application should start listening for connections on the specified address and port, so far so good.
However, the application will be blocked and I can't do anything until someone connects to the server. What if no one connects? How should I handle that? I could specify a receive timeout but what then? It throws an exception, what can I do with that? What I would like is to have some sort of activity on the main application so the user knows the application didn't froze and is waiting for connections. But if a connection doesn't come, it should timeout and close everything.
Maybe I should use asynchronous calls to send/receive methods but they seem confusing and I was not able to make it work, only synchronous work (I'll post my current code below).
Question 2)
Do I need to close anything when some send/receive call times out. As you'll see on my current code, I have a bunch of closes on the socket, but this doesn't feel right somehow. But it also doesn't feel right when an operation times out and I don't close the socket.
In conclusion of my two questions.... I would like an application that doesn't block so the user knows the server is waiting for a connection (with a little marquee animation for instance). If a connection is never established after a period of time, I want to close everything that should be closed. When a connection is established or if it doesn't happen after a period of time, I would like to inform the main application of the result.
Here's some of my code, the rest is similar. The Packet class is a custom class that represents my custom data unit, it's just a bunch of properties based on enums for now, with methods to convert them to bytes and back into properties.
The function that starts to listen for connections is something like this:
public void StartListening(string address, int port) {
try {
byte[] bufferBytes = new byte[32];
if(address.Equals("0.0.0.0")) {
udpSocket.Bind(new IPEndPoint(IPAddress.Any, port));
} else {
udpSocket.Bind(new IPEndPoint(IPAddress.Parse(address), port));
}
remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
int numBytesReceived = udpSocket.ReceiveFrom(bufferBytes, ref remoteEndPoint);
if(numBytesReceived == 0) {
udpSocket.Close();
return;
}
Packet syncPacket = new Packet(bufferBytes);
if(syncPacket.PacketType != PacketType.Control) {
udpSocket.Close();
return;
}
} catch {
if(udpSocket != null) {
udpSocket.Close();
}
}
}
I'm sure that I have a bunch of unnecessary code but I'm new at this and I'm not sure what do, any help fixing up my code and how to solve the issues above is really appreciated.
EDIT:
I should probably have stated that my requirements are to use UDP and implement these things myself in the application layer. You can consider this as homework but I haven't tagged as such because the code is irrelevant and will not be part of my grade and my problem (my question) is in "how to code" as my Sockets experience is minimal and it's not taught.
However I must say that I solved my problem for now I think... I was using threading on the demo application which was giving me some problems, now I'm using it in the protocol connections, makes more sense and I can easily change my custom protocol class properties and read those from the demo application.
I have specified a timeout and throw a SocketException if it reaches the timeout. Whenever an exception like this is caught, the socket connection is closed. I'm just talking about the connection handshake, nothing more. If no exceptions are caught, the code probably went smooth and the connection is established.
Please adapt your answers accordingly. Right now it doesn't make sense for me to marky any of them as the accepted answer, hope you understand.
You have got stuff a bit wrong.
First of all, UDP is connection-less. You do not connect or disconnect. All you do is to send and receive (must specify destination each time). You should also know that the only thing UDP promises is that a complete message arrives on each read. UDP do not guarantee that your messages arrive in the correct order or that they arrive at all.
TCP on the other hand is connection-based. You connect, send/receive and finally disconnect. TCP is stream-based (while UDP is message-based) which means that you can get a half message in the first read and the other half at the second read. TCP promises you that everything will arrive and in the correct order (or will die trying ;). So using TCP means that you should have some kind of logic to know when a complete message has arrived and a buffer that you use to build the complete message.
The next big question was about blocking. Since you are new at this, I recommend that you use Threads to handle sockets. Put the listener socket in one thread and each connecting socket in a separate thread (5 connected clients = 5 threads).
I also recommend that you use TCP since it's easier to build complete messages than ordering messages and build a transaction system (which will needed if you want to make sure that all messages arrives to/from clients).
Update
You still got UDP wrong. Close doesn't do anything other than cleaning up system resources. You should do something like this instead:
public void MySimpleServer(string address, int port)
{
try
{
byte[] bufferBytes = new byte[32];
if(address.Equals("0.0.0.0")) {
udpSocket.Bind(new IPEndPoint(IPAddress.Any, port));
} else {
udpSocket.Bind(new IPEndPoint(IPAddress.Parse(address), port));
}
remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
while (serverCanRun)
{
int numBytesReceived = udpSocket.ReceiveFrom(bufferBytes, ref remoteEndPoint);
// just means that one of the clients closed the connection using Shutdown.
// doesnt mean that we cant continue to receive.
if(numBytesReceived == 0)
continue;
// same here, loop to receive from another client.
Packet syncPacket = new Packet(bufferBytes);
if (syncPacket.PacketType != PacketType.Control)
continue;
HandlePacket(packet, endPoint);
}
} catch {
if(udpSocket != null) {
udpSocket.Close();
}
}
}
See? since there are no connection it's just waste of time to close a UDP socket to start listening from another one. The same socket can receive from ALL udp clients that know the correct port and address. That's what the remoteEndPoint is for. It tells which client that send the message.
Update 2
Small update to make a summary of all my comments.
UDP is connectionless. You can never detect if a connection have been established or disconnected. The Close method on a UDP socket will only free system resources. A call on client.Close() will not notify the server socket (as it will with TCP).
The best way to check if a connection is open is to create a ping/pong style of packet. i.e. the client sends a PING message and the server responds with a PONG. Remember that UDP will not try to resend your messages if they do not arrive. Therefore you need to resend the PING a couple of times before assuming that the server is down (if you do not receive a PONG).
As for clients closing you need to send your own message to the server telling it that the the client is going to stop talking to the server. For reliability the same thing goes here, keep resending the BYE message until you receive a reply.
imho it's mandatory that you implement a transactional system for UDP if you want reliability. SIP (google rfc3261) is an example of a protocol which uses transactions over UDP.
From your description I feel you should use TCP sockets instead of UDP. The difference is
TCP - You wait for a connection at a particuler IP:Port some user can connect to it and until the socket is closed can communicate by sending and receiveing information. This is like calling someone on phone.
UDP - you wait for a message at some IP:Port. User who wants to communicate just sends a message through UDP. You will receive the message through UDP. The order of delivery is not guaranteed. This is more like sending a snail mail to someone. There is no dedicated communication channel established.
Now coming to your problem
Server
Create a Socket with TCP family.
Either create a thread and accept the connection in that thread or use the BeginAccept apis of Socket.
In the main thread you can still display the ticker or whatever you want to do.
Client
Connect to the server.
Communicate by sending and receiving data.