I've got a little problem with the .Net Sockets in C#.
I programmed a client and a server working with TCP.
As the client is opened it sends a handshake to the server. The server answers with it's state (clientexists, clientaccepted,...). After that the application sends a getdata-request, abandons the connection and listens for the server's 'response'. Now, the server builds a connection to the client and sends all the data the client needs.
The code and everything else works, but the problem:
On our company testserver it works fine, on the live server only the handshake works. After it the client doesn't receive any more data. Serverapplication is the same on both servers.
I thought the problem was caused by some firewall (server wants to build a tcp connection to the client -> not good), but the system administrator said there is no firewall that could block that.
Now I'm searching for a ('cheap') solution that doesn't take too much time and changes in code. If anyone knows how to theoretically solve that, that would be great.
BTW: I am not allowed to do anything on the live server other than run the serverapplication. I don't have the possibility to debug on this server.
I can't publish all of my code, but if you need to see specific parts of it, ask for it please.
---EDIT---
Client-Server communication
1) Client startup
Client send handshake (new tcp connection)
2) Server validates handshake and saves IP
Server responds with it's client state (same tcp connection)
3) Client acknowledges this response and abandons this connection
Client sends getdata-request (new tcp connection)
Client abandons this tcp connection, too
4) Server receives getdata-request and collects the needed data in the main database
Server sends all the collected data to the client (multiple tcp connections)
5) Client receives all data and displays it in it's GUI (multiple tcp connections and the order of the data is kept by working with AutoResetEvents and Counts of sockets to send)
This is the main part my code does. It's by far not the best but it was for me as I wrote it I guess. Step one, two and three work as intended. The processing of the data works fine, too.
Another thing i forgot to mention is that the solution uses two Ports '16777' and '16778'. One to receive/listen and one to send.
My code is based on the MSDN example of the asynchronous server and client.
Sending a handshake (and getdata-request)
public void BeginSend(String data)
{
try
{
StateObject state = new StateObject();
state.workSocket = sender;
byte[] byteData = Encoding.UTF8.GetBytes(data);
sender.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback((IAsyncResult e) =>
{
Socket socket = (Socket)e.AsyncState;
SocketBase.StateObject stateObject = new SocketBase.StateObject();
stateObject.workSocket = socket;
socket.BeginReceive(stateObject.buffer, 0, 256, SocketFlags.None, new AsyncCallback(this.ReadCallback), (object)stateObject);
}), sender);
sender = RetrieveSocket(); //Socketreset
Thread.Sleep(100);
}
catch /*(Exception e)*/
{
//--
}
}
Server listener
public void StartListening()
{
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(System.Int32.MaxValue);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
//--
}
}
public void AcceptCallback(...);
public void ReadCallback(...);
Socket send
private void Send(Socket handler, String data)
{
Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.UTF8.GetBytes(data);
// Begin sending the data to the remote device.
t.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), t);
}
Socket send all data part (answer to getdata-request | socToHandle should be the socket of the previous connection of the getdata-request)
private void SendAllData(Socket socToHandle, string PakContent)
{
#region IsThereADatetime? //Resolve a given datetime
#region GiveClientNumberOfPackets //Send the client info about how much he has to receive (See line below)
Send(socToHandle, "ALERT#TASKCOUNT;OPT-" + GetBestDate(dateStart) + EndSocket);
#region #SendResouces
#region #SendGroups
#region #SendTasks
}
Looking through my old code I have one idea =>
Could I send everything over the same connection by changing:
Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
(which creates a new connection) to something that uses the same connection?
If that would work, how can I do that?
And would the listener part of the client still receive single packets?
Servers and their environment are configured to handle incoming requests properly. Clients are usually behind a router, which by default make them unable to receive incoming connections from outside their network (a good thing).
To enable incoming connections, you could configure your router to forward all requests for a certain port number to your machine. No one else on your network would be able to run the client then, though.
This is why in a typical multiple clients-single server environment, the client makes all the connections, and only the server requires any changes to the network landscape.
I don't know why you chose to connect to the clients from the server side, but I would strongly advise against this - any cheap solution that uses this mechanism may turn out to be very expensive in the end.
Related
I have just recently started development for a server - multiple clients application using Socket.
The server doesn't need to keep track of the connected clients; If there is a client that requests for connection, server accepts it. If there is a request from any client (to get some data), server will response to that client.
/// <summary>
/// Callback when server accepts a new incoming connection.
/// </summary>
/// <param name="result">Incoming connection result object.</param>
private void AcceptedCallback(IAsyncResult result)
{
try
{
Socket clientSocket = _socket.EndAccept(result); // Asynchronously accepts an incoming connection attempt
if (clientSocket.Connected) // Check if the client is in 'Connected' state
{
StateObject state = new StateObject();
state.clientSocket = clientSocket;
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, // Start listening to client request
ReceiveCallback, state);
}
else
{
clientSocket.Close(); // Terminate that client's connection
Log.writeLog("TCPServer(AcceptedCallback)"
, "Client's status is not connected.");
}
}
catch (Exception ex)
{
Log.writeLog("TCPServer(AcceptedCallback)"
, ex.Message);
clientSocket.Close();
}
finally
{
Accept(); // Start to accept new connection request
}
}
I have 3 questions about this:
For each BeginReceive that I create for the newly connected client, does my server application creates a new thread/object to hold that client?
If after the client is connected, and the network cable is pulled off at the client side and plug back in, the client will connect to the server again and this is considered a new connection on the server, if this scenario occurs again and again, will my server program crashes?
Hence, do I need to keep track of each client that is connected to the server, and find a way to track their state so I can call Close/Dispose on them?
So far in my testing for scenario 2, there are no abnormalities detected in my server program, but I hope someone would help clarify this for me. Thank you.
No, it will use a IO completion thread from a pool of threads.
No, you can code and should code to cater for this. If something happens on the client side that the OS can detect, it will send a TCP fin/ack to the server. This should result in any BeginXXX method still waiting to go the Async Callback Method. From there your call to EndXXX method should either throw an exception or return zero bytes being read from the socket.
This depends on what you mean by keep track of to dispose of them properly. If you mean dispose of them if you detect an error, no, you can put clean up code in your EndXXX methods. If you mean so that you can signal clients gracefully if you shut the server down, then yes.
I want to learn about socket communication so I decided to try to write WP 8.1 text communicator. It is based on TCP sockets. I almost managed to finish it, but I am searching for improvemenets.
What is worth mentioning I use a socket server between phones (console application), to avoid problems with private ip addresses. It contains information about all connected users and forwards messages to clients (for instance user A sends message to user B, so firstly message goes to server and server forward it to destination address).
The problem appeared when i realized that I need to send special messages from server to client and vice versa (for example when two clients want to have conversation, they send request to server, so it knows where to forward messages).
This is my connection listener method from server application
private void ConnectionListener()
{
IPEndPoint localDataEndPoint = new IPEndPoint(IPAddress.Parse(LocalIpAddress), 1234);
IPEndPoint localMessageEndPoint = new IPEndPoint(IPAddress.Parse(LocalIpAddress), 4321);
Socket dataConnectionListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Socket messageConnectionListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
dataConnectionListener.Bind(localDataEndPoint);
dataConnectionListener.Listen(100);
messageConnectionListener.Bind(localMessageEndPoint);
messageConnectionListener.Listen(100);
while (true)
{
TcpSocket.clientDone.Reset();
IAsyncResult tmp1 = dataConnectionListener.BeginAccept(ConnectionCallback, null);
IAsyncResult tmp2 = messageConnectionListener.BeginAccept(ConnectionCallback, null);
TcpSocket.clientDone.WaitOne();
Socket dataSocket = dataConnectionListener.EndAccept(tmp1);
Socket messageSocket = messageConnectionListener.EndAccept(tmp2);
TcpSocket tmpTcpSocket = new TcpSocket(dataSocket, messageSocket);
tmpTcpSocket.Start();
connectedUsersSockets.Add(tmpTcpSocket);
UpdateConnectedUserList();
}
}
catch (Exception ex)
{
Log.E("Connection listener ran into an exception", ex);
}
}
As you can see I have created two TCP sockets to liesten on different ports. dataSocket is for normal messages and messageSocket is for special messages (sorry for confusing names, I have to refractor code).
On client side it works the same way: there are two different socket to communicate with and through the server.
I wanted to avoid managing two sockets rather then one. But the only way I can imagine is that on every received message server would have to check if it's special (and handle it in special way) or just send to client.
The question: Is there a better way to manage these special messages?
Thanks to all in advance!
P.S.
Sorry for my poor english, it's not my native language
I trying to write a TFTP client for a class project.
Using the UdpClient class I can successfully request data from the server but the returned packet never reaches my code.
My firewall is turned off.
I can observe the returned packet in wireshark but UdpClient.Receive blocks indefinitely.
mUdpClient is initialized like this in the constructor: mUdpClient = new UdpClient();
mUdpClient is connected like this
public void connect(String host, int port) {
mServerAddress = System.Net.Dns.GetHostAddresses(host)[0];
var endPoint = new IPEndPoint(mServerAddress, port);
mUdpClient.Connect(endPoint);
}
After the connect I send my request which is successful (as observed in wireshark)
This is what my receive code looks like
private void receiveResponse() {
var newEndpoint = new IPEndPoint(IPAddress.Any, 0);
byte[] response = mUdpClient.Receive(ref newEndpoint);
Console.Out.WriteLine(response);
}
This has been tested on my Surface Pro and a Windows 8.1 VirtualBox VM running under Debian.
Note that since you are using the Connect() method on your UDP socket, you will only see datagrams actually sent from that IPEndPoint. If your remote host for some reason uses a different IPEndPoint to send data back to you, you won't see it. So maybe try not using the default host feature (i.e. don't call Connect...just provide the remote IPEndPoint on each Send() call).
I use c# to create a TCP server to connect to the iOS devices. However, I've found that it can only accept one iOS device at a time. I couldn't figure out what is the problem. Can anyone have a look and see what is the problem?
IPAddress ipadr = IPAddress.Parse(localIP);
System.Net.IPEndPoint EndPoint = new System.Net.IPEndPoint(ipadr, 8060);
newsock.Bind(EndPoint);
newsock.Listen(10);
client = newsock.Accept();
IPEndPoint clientip = (IPEndPoint)client.RemoteEndPoint;
while (true)
{
if (!isDisConnected)
{
data = new byte[1024];
recv = client.Receive(data);
if (recv == 0)
break;
string receivedText = Encoding.ASCII.GetString(data, 0, recv);
}
client.Close();
newsock.Close();
There are two kinds of sockets: The socket that you use to listen (it is never connected) and the sockets that correspond to connections (each socket represents one connection).
Accept returns you a connected socket to the client that was just accepted. Each call to Accept accepts a new, independent client.
If you want to handle more than one client at a time (which is almost always required) you must ensure that a call to Accept is pending at all times so that new clients can be accepted.
A simple model to achieve this is to accept in a loop forever and start a thread for each client that you accepted:
while (true) {
var clientSocket = listeningSocket.Accept();
Task.Factory.StartNew(() => HandleClient(clientSocket));
}
Take a look at AcceptAsync. Each accept operation allows one connection, so you have to call Accept again. AcceptAsync works asychronously and avoids the difficulties of having to create delegates or threads.
The general model is:
Accept operation completes
Hand off AcceptSocket to code that will Receive data asychronously from that socket.
Call Accept again to listen for more clients.
The same principle also works if you want to do synchronous receives.
Check out this question: Server design using SocketAsyncEventArgs
I'm writing a small C# Sockets application. Actually I have two, a server and a client.
The user runs the client, enters the IP and port for the server, presses 'connect', and then once connected they can enter text into a textbox and send it to the server.
The server simply displays either "No connection" or "Connection from [ip]:[port]", and the most recent received message underneath.
The server successfully receives messages, and even handles the client disconnect fine.
Now I'm trying to make it listen again after the client has disconnected but for some reason nothing I try will allow it to start listening again.
Here is part of my code:
Socket socket;
private void listen()
{
socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Any, 12345));
socket.Listen(10);
socket.BeginAccept(new AsyncCallback(acceptAsync), socket);
}
and
private void receiveAsync(IAsyncResult res)
{
Socket socket = (Socket)res.AsyncState;
try
{
int nBytes = socket.EndReceive(res);
if (nBytes > 0)
{
Invoke(new MethodInvoker(delegate()
{
lMessage.Text = encoder.GetString(buffer);
}));
setupReceiveAsync(socket);
}
else
{
Invoke(new MethodInvoker(delegate()
{
lConnections.Text = "No Connections.";
lMessage.Text = "No Messages.";
socket.Shutdown(SocketShutdown.Both);
socket.Close();
listen();
}));
}
}
catch { }
}
The last line: listen(); is what throws the error.
I have tried simply calling socket.BeginAccept() again, but that also throws an exception.
The message I'm getting is:
Only one usage of each socket address (protocol/network address/port) is normally permitted
If I don't call my listen() function and instead just call socket.BeginAccept(), then I get "You must first call socket.listen()"
If I call the socket.listen() function, then it tells me it's already connected and cart start listening.
Once I have made an asynchronous connection, and received several asynchronous messages, how then do I begin receiving again?
Your socket variable already has an listening socket assigned to it the second time you call listen(), which is why it tells you only one usage is permitted. All you need to repeat is the socket.BeginAccept(new AsyncCallback(acceptAsync), socket) call. So try replacing the call to listen() inside your receiveAsync(...) method with socket.BeginAccept(new AsyncCallback(acceptAsync), socket).
In async Begin* is always followed by End*. See Using an Asynchronous Server Socket. Your accept method should be something like:
try {
listener.Bind(localEP);
listener.Listen(10);
while (true) {
allDone.Reset();
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(SocketListener.acceptCallback),
listener );
allDone.WaitOne();
}
} catch (Exception e) {
Server, means that an app that listens on specified port/ip. Is usually, always in a listening mode - that's why it is called a server. It can connect and disconnect a client, but is always in listening mode.
This means, when a server disconnects a client - even then - it is in listening mode; meaning it can accept the incoming connections as well.
Though, disconnection request can come from client or can be forcefully applied by server.
The process for a server is:
Bind to socket
Listen
Accept connections
The process for client is:
Connect to the server
Send/receive messages
There are several ways for server to handle the incoming clients, couple, as follows:
Incoming connections are maintained in a list, for instance within a List<TcpClient>.
One way of handling the incoming clients is through threads. For instance, for each incoming client, spawn a thread that would handle the communication between server and client. For instance, checkout this example.
_
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
Use single thread and use context switching to manage client communications (TX/RX).