I have a server application and a client application.
I'm using socket to communicate between server and client. Everything works fine if there's only one client connect: uploading, downloading all work well.
But if there's another client connect (I start the client application again, which means there're 2 client apps and 1 server app running on my computer), my server starts to mess up: server doesn't receive file upload from client, client couldn't download from server.
In server code, I already used multithreading for each client connection so I can't figure out the problem. Here is my server code:
private void ServerForm_Load(object sender, System.EventArgs e)
{
//...
Thread th = new Thread(new ThreadStart(ListenForPeers));
th.Start();
}
public void ListenForPeers()
{
serversocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serversocket.Blocking = true;
IPHostEntry IPHost = Dns.GetHostEntry(server);
string[] aliases = IPHost.Aliases;
IPAddress[] addr = IPHost.AddressList;
IPEndPoint ipepServer = new IPEndPoint(addr[0], 8090);
serversocket.Bind(ipepServer);
serversocket.Listen(-1);
while (true)
{
clientsock = serversocket.Accept();
if (clientsock.Connected)
{
total_clients_connected++;
AppendText("Client connected...");
Thread tc = new Thread(new ThreadStart(listenclient));
tc.Start();
}
}
void listenclient()
{
// start communication
}
Is there something wrong with my server code that makes it unable to become a multi-clients server system? Help is really appreciated. Thanks in advance.
It looks like you've defined your clientSocket as a global variable to be used by all server threads, instead you want it to be a local reference for each thread. You can do this with a ParameterizedThreadStart:
public void listenForPeers()
{
//Setup the server socket
while(true){
Socket newClient = serverSock.Accept();
if(newClient.Connected){
Thread tc = new Thread(new ParameterizedThreadStart(listenclient));
tc.start(newClient);
}
}
}
void listenclient(object clientSockObj)
{
Socket clientSock = (Socket)clientSockObj;
//communication to client via clientSock.
}
First, you're setting your socket's Blocking property to true. This will block any requests until the previous ones finish...
See here: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.blocking(VS.80).aspx
If you are in blocking mode, and you
make a method call which does not
complete immediately, your application
will block execution until the
requested operation completes. If you
want execution to continue even though
the requested operation is not
complete, change the Blocking property
to false. The Blocking property has no
effect on asynchronous methods. If you
are sending and receiving data
asynchronously and want to block
execution, use the ManualResetEvent
class.
You might want to reconsider doing it this way, and instead use WCF or maybe a web service for uploading the files... it'll be a lot easier, and IIS will handle the threading for you. It's pretty easy to write a web service to upload a file...
http://www.c-sharpcorner.com/UploadFile/scottlysle/UploadwithCSharpWS05032007121259PM/UploadwithCSharpWS.aspx
try this
const int noOfClients = 5;
for(int i=0;i<noOfClients;i++)
{
Thread th = new Thread(new ThreadStart(ListenForPeers));
th.Start();
}
Related
I'm trying to write a chat client/server in c# locally to get familiar with Sockets.
First I start the server with (very simplified) following code:
Server.cs
private readonly MessageManager _messageManager;
private readonly ChatServer _chatServer;
public ChatServerSkeleton()
{
_messageManager = new MessageManager();
_chatServer = new ChatServer();
Console.WriteLine("Server is running on: " + _messageManager.MyAddress);
}
Then I start the Client with +- same way, except I store the serveraddress in the client (I copied the server address into a prompt).
Client.cs
private readonly MessageManager _messageManager;
public ChatClient ChatClient { get; }
public ChatClientSkeleton(IPEndPoint serverAddress, string name)
{
_messageManager = new MessageManager();
ChatClient = new ChatClient(new ChatServerStub(serverAddress, _messageManager), name);
Console.WriteLine($"IPAddress of {name} is: {_messageManager.MyAddress}");
Console.WriteLine($"IPAddress of Server is: { serverAddress}");
}
MessageManager.cs
private readonly TcpListener _serverSocket;
public IPEndPoint MyAddress { get; }
public MessageManager()
{
try
{
//Create server socket on random port
_serverSocket = new TcpListener(IPAddress.Any, FindFreeTcpPort());
//Get host ip address
IPAddress[] localIps = Dns.GetHostAddresses(Dns.GetHostName());
IPAddress localhost = localIps.First(ip => ip.AddressFamily == AddressFamily.InterNetwork);
//Get port of serversocket
IPEndPoint ipEndPoint = _serverSocket.LocalEndpoint as IPEndPoint;
int port = ipEndPoint.Port;
//Create address
MyAddress = new IPEndPoint(localhost, port);
}
catch (Exception ex)
{
Console.Error.WriteLine("Something went wrong with the serversocket:");
Console.Error.WriteLine(ex);
}
}
FindFreeTcp port comes from here: https://stackoverflow.com/a/150974/5985593
Everything up till now seems to work. Let's say for example the server has now 192.168.0.219:51080 and the client 192.168.0.219:51085.
The problem occurs when I'm trying to send a message using this code in MessageManager.cs
public void Send(MethodCallMessage message, IPEndPoint address)
{
try
{
_serverSocket.Start();
TcpClient destination = new TcpClient(address.Address.ToString(), address.Port);
NetworkStream output = destination.GetStream();
MessageReaderWriter.Write(message, output);
destination.Close();
}
catch (Exception ex)
{
Console.Error.WriteLine("Failed to write a message:");
Console.Error.WriteLine(ex);
}
finally
{
_serverSocket.Stop();
}
}
More specific on the _server.Start(); line.
Anyone knows what I'm doing wrong?
Thanks in advance!
EDIT: it runs fine 1 time, when registering the client on the server. But after that if I want to send a message I get the SocketException where target machine actively refused.
I do use AcceptTcpClient() here:
MessageManager.cs
public MethodCallMessage WReceive()
{
MethodCallMessage result = null;
try
{
//_serverSocket.Start();
TcpClient client = _serverSocket.AcceptTcpClient();
NetworkStream input = new NetworkStream(client.Client, true);
result = MessageReaderWriter.Read(input);
client.Close();
}
catch (Exception ex)
{
Console.Error.WriteLine("Failed to receive a message:");
Console.Error.WriteLine(ex);
}
finally
{
//_serverSocket.Stop();
}
return result;
}
This method is used in the ServerSkeleton & ClientSkeleton as follows:
public void Run()
{
while (true)
{
MethodCallMessage request = _messageManager.WReceive();
HandleRequest(request);
}
}
So the flow is basically as follows:
I start the server (instantiate new messagemanager, 3rd snippet
and run serverskeleton (last snippet)
Server prints IP in
console, i copy the ip & start the client
Instantiate client &
set server ip to what I copy pasted
Start client skeleton (last
snippet)
A TcpListener that has called Start() listens for incoming connections and then stacks them on a queue. Once that queue is full then a socket exception results. To remove connections from the queue you need to use the AcceptTcpClient or AcceptSocket methods of TcpListener. This then gives you a connection that you can send and receive data on.
What I am guessing may be happening is that you receive your first incoming client, but dont accept and remove it to send and receive data on, and your subsequent connections are refused as the pending queue list is full (this is just a guess).
There is an overloaded method ... TcpListener.Start(int backlog) ... that allows you to set the size of the pending queue list (so you can have 5, 10 or more connections waiting to be accepted in the TcpListener)
With a server TCP socket the process is that you set it listening on a local address and a port. Clients then try to connect to that endpoint. When they connect the TCP listening socket accepts the connection and then passes that to a socket which is the socket on which data is transfered. The listening socket carries on listening for new connections, it doesnt itself transmit data.
I hope that makes sense ?
So the server would behave more like this ...
_serverSocket.Start();
TcpClient myAcceptedConnection = _serverSocket.AcceptTcpClient();
// in synchronous blocking socket situation the program flow halts
// here til a connection is established
// once you have a connection ... do stuff with myAcceptedConnection
if you wished to avoid the blocking scenario you can use TcpListener.Pending() to see if you have any connections waiting in the queue
EDIT 1:
Ok so the only weird thing I see is that you call the _serverSocket.Start() method in the MessageSend method ? A server doesnt normally start by sending out a message ... it normally waits listening for a connection, receives and reads the connection and then replies (or it might send out a greeting or such on connection).
Personally I would separate the listening aspect of the server from the sending and receiving of data ... have it in its own separate method, after all you want your server to be listening for incoming connections until you close it down. When you detect an incoming connection (perhaps by checking Pending() in a loop), then you can accept it and send and receive on the new TcpClient. When you are finished with whatever data you are transmitting/receiving on that client you can close it down , if thats what you want ... you dont need to close and open a tcp connection every time you send a message, you can leave it open til you are finished with it, in fact opening and closing tcp connections generates a bit of overhead in the handshake protocol that they go through.
There are caveats though ... Tcp connections can become "half open" especially with wireless which can lead to issues. Its a bit complicated to get into here, but I recommend this stellar set of articles by Stephen Cleary as a good read through. Read the whole blog, as there is a ton of good info in there.
So, back to simple, I would have ...
A serverStart() method where you start your server listening.
A serverAccept() method where you check if you have any pending connections and accept them if they are there.
A clientConnect() method for your client where you connect to a server
Read() and Write() methods for the server and the client where you do the data transmission.
Normally the flow would be ...
Server Listens
Client Connects
Server Accepts
Client Sends
Server Receives
(then server sends/receives, client sends/receives)
everything closes and shuts down
I'm trying to send and receive to/from a UDP multicast address using UWP. It works perfectly the first few times, but after a while of this send-receive process, it will lock on the receiving part. I changed from an async approach to a synchronous one but still the same. Even if I instantiate a new UDP client, the port is blocked until the app is restarted. Anything I'm doing wrong?
private UdpClient udp;
//inside main function:
if (udp == null)
{
udp = new UdpClient(new IPEndPoint(IPAddress.Any, portNumber));
//^the second time this is called, it will complain about port reuse
udp.Client.ReceiveTimeout = udp.Client.SendTimeout = 3000;
//udp.Client.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.ReuseAddress, true);
//^invalid
}
//await udp.SendAsync(data, data.Length, , portNumber);
//I changed from async to synchronous in case it was the issue, but no.
udp.Client.SendTo(data, new IPEndPoint(IPAddress.Parse(ipString), portNumber));
//the receive used to be async, too
byte[] receivedByte = new byte[udp.Client.ReceiveBufferSize];
try
{
udp.Client.Receive(receivedByte);
}
catch (Exception ex)
{
udp.Client.Shutdown(SocketShutdown.Both);
udp = null; // added these, but port still blocked until restart
}
I'm using UWP, and there are methods on class library that aren't here.
After putting UdpClient in a using () statement instead of declaring it as a private field, and limiting its scope by putting it in a short async method, I am not having these problems anymore.
A client need to build several tcp connections to server simultaneously.
My Server's code is below.
while (_running)
{
if (!_listener.Pending())
{
Thread.Sleep(100);
continue;
}
TcpClient client = _listener.AcceptTcpClient();
}
And my client's code is below.
for (int i = 0; i < num; i++)
{
TcpClient tcp = new TcpClient();
tcp.Connect(_server);
}
The first connection is success. But the second connection is failed due to server's no response(Actually server are listening tcp connection).
However, if I add Thread.Sleep(1500) after each of tcp.Connect(), all connections are success. But this situation is only true if there are one client and one server. If there are many clients then how can I ensure each connection that can be accepted by server? Also why I add Thread.Sleep can make such connections succeed?
I had the same task. I looked for canonical implementation of this task for .Net with no luck.
The approach I use now is descibed below.
Main idea
We need listener to receive connection, give the connection to the handler, and as soon as possible start listen for a new connection.
Implementation
AutoResetEvent _stopEvent = new AutoResetEvent(false);
object _lock = new object();
public void StartListening()
{
_listener.BeginAcceptTcpClient(ConnectionHandler, null);
_stopEvent.WaitOne();//this part is different in my original code, I don't wait here
}
public void StopListening()
{
lock(_lock)
{
listener.Stop();
listener = null;
}
_stopEvent.Set();//this part is different in my original code
}
void ConnectionHandler(IAsyncResult asyncResult)
{
lock(_lock)
{
if(_listener == null)
return;
var tcpClient = _listener.EndAcceptTcpClient(asyncResult);
var task = new MyCustomTask(tcpClient);
ThreadPool.QueueUserWorkItem(task.Execute);
_listener.BeginAcceptTcpClient(ConnectionHandler,null);
}
}
I am still not very confident in calling _listener.BeginAcceptTcpClient in ConnectionHandler, but I haven't found alternative way.
Since there are still no satisfied answers and I finally use different approach to handle my case. I found out that using class Socket is faster and more stable than using TcpListener and TcpClient. I tried different approach to use TcpListener and TcpClient. Firstly, I used TcpListener.AcceptTcpClient to listen client with and without TcpListener.Pending but there is still possibly ignoring some client connection. Sencondly, I used asynchronous method, TcpListener.BeginAcceptTcpClient and TcpListener.EndAcceptTcpClient but still no succeeded, still ignoring some client connection. Finally using Socket.Accept instead of TcpListener.AcceptTcpClient, the former one has nearly no delay and really fast to response to client.
I have a Server Application written in C# .NET and running on Windows XP SP3.
I am using asynchronous sockets programming for handling around 500 clients.
But I got a problem to entertain more than 15 client connections.
My application got shut down when 1 more client connected after 15 clients; I am not
understanding whether the problem is with my OS or is a tcp connection limitation problem in Windows XP.
Please help to solve out this issue, please suggest any solution.
Update:
Here is my piece of code.
public const int MAX_CLIENTS = 200;
public AsyncCallback pfnWorkerCallBack;
private Socket[] m_workerSocket = new Socket[MAX_CLIENTS];
// class for worker socket & callback method & data buffer
private SocketPacket[] m_workerSocketPkt = new SocketPacket[MAX_CLIENTS];
// page Load
m_mainSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, 4321);
// Bind to local IP Address...
m_mainSocket.Bind(ipLocal);
// Start listening...
m_mainSocket.Listen(MAX_CLIENTS);
m_mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
// called when client is connected
public void OnClientConnect(IAsyncResult asyn)
{
try
{
m_clientCount = setclient();
SocketPacket abc = new SocketPacket();
m_workerSocketPkt[m_clientCount] = abc; //assigning with SocketPacket class
m_workerSocketPkt[m_clientCount].m_currentSocket =
m_mainSocket.EndAccept(asyn); //transferring connection to other thread
m_workerSocketPkt[m_clientCount].m_clientCount = m_clientCount;
m_workerSocketPkt[m_clientCount].templist = abcde; //assigning Amj (list) class
m_workerSocket[m_clientCount] = m_workerSocketPkt[m_clientCount].m_currentSocket;
pfnWorkerCallBack = new AsyncCallback(m_workerSocketPkt[m_clientCount].OnDataReceived); //defining AsynCallBack function for the accepted socket
m_workerSocketPkt[m_clientCount].oldpfnWorkerCallBack = pfnWorkerCallBack;
m_workerSocketPkt[m_clientCount].data_rec = false;
m_workerSocketPkt[m_clientCount].data_sent = false;
m_workerSocketPkt[m_clientCount].m_currentSocket.BeginReceive(
m_workerSocketPkt[m_clientCount].dataBuffer, //assigning data buffer for receiving for the socket
0, //assigning data buffer offset for receiving for the socket
m_workerSocketPkt[m_clientCount].dataBuffer.Length, //assigning maximum data length for receiving for the socket
SocketFlags.None, //socket flags
pfnWorkerCallBack, //AysnCallBack delegate
m_workerSocketPkt[m_clientCount].m_currentSocket //state
);
m_mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null); //start invitation for other new sockets
}
The Max Client Value is here 200 and worker sockets also, so it should handle 200 clients but I think it's creating a problem in receiving data from more than 15 clients because every client that is connected is continuously connected and sends data to the server.
Increase the m_workerSocketPkt array (or m_workerSocket) to more than 15 or convert it to a List<>. (I'm guessing since you did not show it's declaration)
Your even the most basic Windows XP system should be able to handle 1000 connections. TCP is allows thousands of connection per client machine. (I wouldn't suggest more than 100K per server)
If your program is failing its likely to be a bug in your code. Is possible it producing an error your are ignoring? What is the error your program gets?
I'm using the code below, it seem sometime the socket is not released
How did I found that?
by using process explorer(from sysinternal),
proprieties on the application
then going into TCP/IP tab.
I can see the port being used by typing "netstat -a" into a console
My problem is, after a while (like 5 weeks) there is like 40 port used by the application while it should be zero.
Anyone know why it does that?
public void Connect()
{
try {
// Resolve server address
IPHostEntry hostadd = Dns.GetHostEntry(TimeServer);
IPEndPoint EPhost = new IPEndPoint(hostadd.AddressList[0], 123);
//Connect the time server
UdpClient TimeSocket = new UdpClient();
TimeSocket.Connect(EPhost);
TimeSocket.Send(SNTPData, SNTPData.Length);
SNTPData = TimeSocket.Receive(ref EPhost);
TimeSocket.Close();
if (!IsResponseValid())
{
throw new Exception("Invalid response from " + TimeServer);
}
} catch(SocketException e)
{
throw new Exception(e.Message);
}
}
You're blocking forever on:
SNTPData = TimeSocket.Receive(ref EPhost);
If the socket never receives a packet it will sit there waiting until the process dies.
You'll need to close the socket by calling TimeSocket.Close() on a different thread or by setting a timeout on the receive using SetSocketOption.