i'am trying to do Socket programming in C# and now i need to understand that do we need array of
sockets in Server-side in order to handle multiple clients or one socket in server-side is sufficient for
handling many clients;
And need to configure whether all data from server to client has been reached and the availability of server,discarding the client request .
Do we need to create multiple thread to handle each client also ? and i need to handle each client separetely.
Each connection will require a new socket. As spender says, you only listen with one socket, the socket API will create the other sockets when connection requests come in.
Read the documentation for accept
One listening socket can service many clients.
You can use one socket to response multiple clients. When a client connet with the server, your application creates a socket to attend this conection.
Please have a look at Writing scalable server applications using IOCP. This's a good tutorial on how to create a robust server application.
you create one listener(welcome socket) which creates a dedicate connection socket for every accepted client.
I think you need some thing like.
private void listen(){
TcpListener listener = new TcpListener(5000);
listener.Start();
while (true)
{
// Accept a new client
Socket clientSocket = listener.AcceptSocket();
//Create a thread for every client.
ParameterizedThreadStart pThreadStart = new ParameterizedThreadStart(handleClient);
Thread thread = new Thread(pThreadStart);
thread.Start(clientSocket);
}
}
Related
I get an exception when doing this in one thread:
var listener = new TcpListener(new IPEndPoint("127.0.0.1", 3536));
listener.Start();
System.Net.Sockets.SocketException (0x80004005): Address already in use
and this in another thread:
var client = new TcpClient(new IPEndPoint("127.0.0.1", 3536));
I know that I can't create two sockets on the same port, but I want one thing and the other receiving.
What I want to achieve is inter-process communication between a LOCAL C# and Python program. I've opted for sockets cause pipes work differently on Windows and Unix Systems and I wanted the possibility to outsource one program to another machine.
Edit: The TCP listener runs flawlessly when I remove
var client = new TcpClient(new IPEndPoint("127.0.0.1", 3536));
Edit2: I've had a
Thread.Sleep
on my main Thread. If I replace it with
while (!client.Connected) client.Connect(ipEndPoint)
Console.WriteLine(client.Connected) // this reaches
I don't currently know about data-transfer yet
You are using the wrong constructor.
TcpClient(IPEndPoint)
Initializes a new instance of the TcpClient class and binds it to the specified local endpoint.
What you probably want is this:
TcpClient(String, Int32)
Initializes a new instance of the TcpClient class and connects to the specified port on the specified host.
See TcpClient constructors
Some knowledge: A client needs a free port too. Normally it will binds to a random free port. For a local connection are two sockets required - one for the client and one for the server.
I'm working on a peer-to-peer file sharing application that can be used to transfer files without having a central server.
It works like a charm when it comes to one-to-one file transfer, however I originally planned it in a way, that the sender can send files to multiple clients.
The app uses TCP Hole Punching so port forwarding is not necessary. The problem is, that in order to make TCP hole punch work, I need to specify a local port for each TCPClient. Thus, I need to bind the sockets.
TCPClient client = new TCPClient(port);
The problem is, that when it comes to the creation of the a new client (after establishing a connection), I'll get the error which states I am unable to bind a new socket.
As far as I'm concerned, a socket is identified as a Local Port with Local IP AND Remote Port with Remote IP AND Protocol. Thus, if two sockets differ in one of these 4, they can be handled as separate connections.
Yet, I still get exception.
How can I do TCP Hole Punching with multiple clients? According to this wikipedia page, it should work, if the sender does not bind the sockets.
Here is the code for my Connect() method in my custom NetClient class. (It contains a TcpClient and represents a connection with a remote endpoint.)
private async Task<bool> Connect(string _ip)
{
IPEndPoint _endPoint = new IPEndPoint(IPAddress.Any, port);
tcpClient = new TcpClient(_endPoint);
int tick = timeOut;
while (tick >= 0)
{
try { await tcpClient?.ConnectAsync(_ip, port); }
catch { }
if (tcpClient.Connected) return true;
tick--;
await Task.Delay(1000);
}
return false;
}
Still, no luck. Can someone help please?
Okay, I've found a solution! For those who might stuck with the same problem, apparently there is an option to tell the TCP socket that the local endpoint can be reused.
Depending on the OS and the TCP implementation, you can add the option SO_REUSEADDRESS and SO_REUSEPORT for the socket. This will make the socket ignore endpoint duplication. (As far as I'm concerned it only works on the local endpoint.)
Head over this website for further information on the topic, it is a very good read.
Now for that, you will need to set these properties BEFORE binding the socket. So you will need to call socket.Bind() separately from the TcpClient constructor.
Use TcpClient.Client to access the socket of the tcpClient.
Proper way of creating a TcpClient with reusable local endpoint:
TcpClient client = new TcpClient();
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, true);
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.Client.Bind(new IPEndPoint(IPAddress.Any, port));
After these steps, you should not experience any problem with socket binding. Hope that helped!
I'm trying to have different Network Stream for each client that i'm listening to (using TCPListener)
here's an example code:
while(listener.Pending())
{
Socket sock = listener.AcceptSocket();
NetworkStream stream = new NetworkStream(sock);
list.Add(stream);
}
my question is, will the list consist of different network streams, one for each client that tries to make connection?
ty
Yes, you'll get one NetworkStream per socket, and Accepted sockets are client-specific.
But you're misusing the Pending function. You should use the asynchronous methods BeginAcceptSocket or AcceptAsync. The while(listener.Pending()) loop will exit as soon as no client is trying to connect, which will effectively prevent you from getting connections.
I have a listener that listens to the localhost on an assigned portnumber like this:
TcpListener listener = new TcpListener(localIP);
listener.Start();
while (true) {
listen:
if (!listener.Pending()) {
Thread.Sleep(100);
goto listen;
}
Socket socket = listener.AcceptSocket();
}
Now the same program should make a connection to other instances of this program like this:
TcpClient client = new TcpClient(localIP); //localendpoint should use same port
client.Connect("localhost", remotePort);
As you can see I'm binding the same IPEndPoint localIP for both the listener and client. So that whenever another instance of the program has a connection with this one, the socket in the listener could give me it's RemoteEndPoint. So that I don't get a random port number generated by the system. Of course this won't work and I get this error:
Only one usage of each socket address (protocol/network address/port)
is normally permitted
Since both listener and client are binded to the same IPEndPoint localIP.
Is there a workaround so that I can bind a listener and client to the same EndPoint? Because I want to get the portnumber from socket.RemoteEndPoint in the listener. This portnumber should be the portnumber that is assigned to each individual instance of the program.
Well, based on the comments from the question, the best solution would be just to send the port number the program is listening to over the socket connection.
I recommend switching to WCF for your communications. It gives you a lot of handy tools for abstracting over serialization, the transport protocol, security, configuration, etc. Eventually, WCF lets you build service-oriented apps for a diverse client ecosystem easier than doing all the hard work yourself.
One of the features WCF has to offer is a so-called Duplex Binding, which should give you what you want: a connecting client immediately announces a way to be called back.
If you still need to communicate your network topology, than you can still do so using WCF; And for that I recommend implementing a separate service interface that takes care of network topology exclusively.
A tutorial + example on getting started with WCF, and creating clean code can be found here and here.
I have been working with the following code published on msdn:
http://msdn.microsoft.com/en-us/library/fx6588te.aspx
I understand that the server application is not blocked whilst the application is waiting for new clients.
However can this application (or even sockets) for that matter handle multiple concurrent requests?
What would happen if client A and B connected at the same time?
If client A connects and the handling of its request takes 5 seconds, if client B connects a second later must it wait for client A to finish before its processing can start?
Or will client A and client B's requests be handled concurrently?
I have done some testing with this by putting Thread.Sleep(n) commands in between the receive/send data in the socket listener code. I can then send multiple requests to the socket and they appear to be handled. However the socket always handles them on the same thread id - which makes me believe that it isnt actually happening concurrently.
Especially given the description by microsoft that this app simply doesnt block whilst awaiting for new connections - does that mean it can handle concurrent connections?
[Update 2014]: It seems that the example has been modified since this answer was posted, as noted in this thread. The MSDN example now handles multiple incoming connections properly. Anyway, the general approach described here is correct and perhaps it can provide additional clarification.
When doing socket communication, you basically have a single listener socket for all incoming connections, and multiple handler sockets for each connected client.
Listening to incoming connections
When you start listening to a port, you create a socket with a callback method for incoming connections (this is referencing the example you mentioned). That's the one-and-only listener socket for that port number:
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
This line tells the listener to invoke the AcceptCallback method whenever a new client is connected (new connection callback). That method is the one which should do its work quickly, since it blocks other incoming connections.
Creating dedicated handler sockets
That is also why AcceptCallback must immediately create a dedicated "handler" socket with its own background data callback method (ReadCallback):
// inside AcceptCallback, we switch to the handler socket for communication
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state); // fired on a background thread
From that moment on, ReadCallback method is invoked whenever some data is received by your newly connected client.
Also, before returning, AcceptCallback needs to call listener.BeginAccept again, to continue listening to new incoming connections:
// this is the same server socket we opened previously, which will now
// continue waiting for other client connections: it doesn't care about
// the actual data transmission between individual clients
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
This part is omitted from the MSDN example, meaning it can only receive a single connection.
Receiving data
As soon as you get a packet of data from your client, ReadCallback method will be invoked. So, inside this data callback method, you need to read and process the received data, and then invoke the same BeginReceive method again (again, with ReadCallback as its data callback method).
[Edit]
The problem with MSDN example is that it allows connection of only a single client (listener.BeginAccept is called only once). To allow mulitple concurrent connections, you need to create a receive socket using handler.BeginReceive, and then call listener.BeginAccept to start listening to new clients.
Every socket will have a listen queue associated with it. This will have the pending/partially accepted incoming connections. The max number number of pending connections can be defined programmatically in listen() API, which is nothing but 'listener.Listen(100)' in this example. Having had this as 100 here, the socket 'listener' can have 150 (=2*100/2) pending connections in the listen queue.