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.
Related
I am able to communicate with socketTest with the same ip address, but within UNITY I get an error message
SocketException: The requested address is not valid in the context.
I tried
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Parse(sHostIpAddress), nPort));
sHostIpAddress is not 127.0.0.1
How to can i fix it?
This is not really specific to Unity but rather c# in general.
Socket.Bind is for binding the socket to a specific local endpoint! Such as for example you want to limit the socket to a specific local network adapter / address (by default it will use any/all) or a specific local port (by default it will pick any free local port)
Use the Bind method if you need to use a specific local endpoint. You must call Bind before you can call the Listen method. You do not need to call Bind before using the Connect method unless you need to use a specific local endpoint.
Usually you use Bind mostly for the server side for listening and waiting for incoming connections or for connectionless protocols like UDP.
You most probably simply want to rather use Socket.Connect for establishing a connection to a remote server.
When using Connect without Bind then it will simply pick the network adapter / address it finds to be the best fit for reaching the given host address and picks the next free local port.
However, in general I would recommend to rather use TcpClient instead of composing and configuring the Socket "manually" (except the use case requires it).
var tcpClient = new TcpClient(sHostIpAddress, nPort);
This constructor will automatically start a connection attempt. TcpClient is an IDisposable and cleans up the underlying socket, stream etc when it is disposed. It also is (in my eyes) way easier to configure and to sent and receive data with it.
Using the following code, my client fails to connect my server:
private static TcpClient client = new TcpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 0));
private static IPEndPoint destinationEp = new IPEndPoint(IPAddress.Parse("192.168.0.100"), 1234);
//...
client.Connect(destinationEp);
Using TcpClient client = new TcpClient() instead will work.
In the original case, my understanding is that I am setting the local IP to the local machine, and using any available port as the local port to facilitate communication. My suspicion is that the server is trying to connect to the client using the IP "127.0.0.1", which wouldn't work, but I don't know this for sure.
Why do I have to use new TcpClient() instead of new TcpClient(myEndpoint) to successfully establish a server connection?
See the docs:
Initializes a new instance of the TcpClient class and binds it to the specified local endpoint.
Emphasis mine. You use that constructor only if you want to control the local part of the socket. See also the remainder of the docs:
You do not need to specify a local IP address and port number before connecting and communicating. If you create a TcpClient using any other constructor, the underlying service provider will assign the most appropriate local IP address and port number.
So your suspicion is correct. You're basically telling the network stack that you want your end of the socket to be bound to 127.0.0.1:0, which won't work for outbound connections.
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 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'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);
}
}