c# fixed tcp client local endpoint port causes SocketException - c#

Can i unbind socket from local endpoint? For security purposes, i need to fix source port for TCP communication. In this client code i fix source port to 42448:
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint localEP = new IPEndPoint(IPAddress.Parse("192.168.1.123"), 42448);
s.Bind(localEP);
s.Connect(remoteEP);
s.Send(new byte[] { 0x01, 0x02, 0x03 });
s.Close();
It works only once. Second time it throws SocketException (that address already in use) on the s.Connect line as i see in netstat, there is one connection from this source port 42448 with TIME_WAIT state, even if i close the app. after about 1 minute this TIME_WAIT connection disappears and i can run my code, but again just once. how can i properly unbind this socket so i can run code many times?
Update 1
it is not a server socket, so there is no listening here. LingerOption is also doesnt work:
LingerOption lo = new LingerOption(false, 0);
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);

Related

C# TcpClinet LingerOption with Close() not skips TIME_WAIT

I am trying to contact to server with C# TcpClient for lots of time. For example, I connect to server for 5s, disconnect then try connect to server in 10s, and repeat...
But eventhogh I set LingerOption and ResueAddress Option as true, ExtendedSocketExcption came out when I reconnect to server.
Here is my code. (.Net5, Windows 10)
TCPSocket = new TcpClient(new IPEndPoint("10.10.0.100", 50010));
TCPSocket.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
LingerOption lo = new LingerOption(true, 0);
TCPSocket.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
TCPSocket.Connect(new IPEndPoint("10.10.0.50", 50010));
TCPSocket.ReceiveTimeout = 5000;
//Do somthing
TCPSocket.Client.Shutdown(SocketShutdown.Both);
TCPSocket.Close();
Thread.Sleep(5000);
TCPSocket.Connect(new IPEndPoint(SRE3021IP, SRE3021TCPPort)); //ExtendedSocketExeption
And I check on cmd with command netstat -ano | findstr 50010 while thread was sleeping.
TCP 10.10.0.100:50010 10.10.0.50:50010 TIME_WAIT 0
The TIME_WAIT state remained about 30~1 min then It disappeared...
I don't know why linger option was not applied.
Setting a LingerOption doesn't stop a socket from closing. It delays the close() to allow any unsent data in the buffer to be sent. This allows an application to move on to the next phase with a slow network. The socket will still close.
ReuseAddress has nothing to do with reusing an existing socket (believe it or not), it allows a Listening Socket to bind to an existing listening port. This is a very bespoke behaviour and requires other process interops to have two different applications listening on the same port. This option has no useful meaning on an outbound socket connection.
Your problem stems from the fact you're setting a source bind with this line:
TCPSocket = new TcpClient(new IPEndPoint("10.10.0.100", 50010 ));
If you want to set a source port you have no option but to wait for the OS to clean out the socket from the connection list which means waiting for the TIME_WAIT to expire.
If you don't want to set a source port, (and these days their are very few reasons to actually set a source port) but still want to select a specific source IP address interface then you can use:
TCPSocket = new TcpClient(new IPEndPoint("10.10.0.100", 0));
If you want Windows to just choose the most appropriate outgoing interface, (and port), then use:
TCPSocket = new TcpClient();

Socket already in use broadcast [duplicate]

I'm trying to make two applications. One will be sending data to a specific udp port, and the other will be reading it.
I am having 2 problems:
when running on the same machine, I get an error: "Only one usage
of each socket address (protocol/network address/port) is normally
permitted" so I need to figure out how to test it if I cannot have
multiple socket connections at the same port.
when I tried using
an internal ip of another computer within my network, I did not get
any reading at all.
server:
private Socket sock;
private const int PORT = 5000;
public void start()
{
sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sock.ReceiveTimeout = 1;// seconds
sock.SendTimeout = 1;// seconds
IPEndPoint iep = new IPEndPoint(IPAddress.Any, PORT);
EndPoint ep = (EndPoint)iep;
sock.Bind(iep);
MulticastView view_obj = new MulticastView();
while(true)
{
try
{
if (sock.Connected)
{
sock.Send(Serializer.ObjectToByteArray(view_obj));
}
}catch(Exception ex){
Console.WriteLine(ex);
}
Thread.Sleep(1000); // milliseconds
}
}
client:
IPAddress ip = IPAddress.Parse("127.0.0.1");
IPEndPoint iep = new IPEndPoint(ip, PORT);
EndPoint ep = (EndPoint)iep;
UdpClient client = new UdpClient(PORT);
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
// or using: Byte[] receiveBytes = client.Receive(ref ep);
Byte[] receiveBytes = client.Receive(ref RemoteIpEndPoint);
MulticastView view;
view = (MulticastView)Serializer.ByteArrayToObject(receiveBytes);
Note that I need separate apps (on separate processes).
You can't have 2 separate sockets open on the same IP address / port. Each IP/Port is a unique mailbox, so to speak. (Technically, it is possible to have 2 processes attached to the same socket, under certain circumstances, but that isn't relevant to your problem). The rule is simple, but the workarounds are several.
I would ask if the client really needs to have a standard port number. Normally, UDP/TCP clients just use a random socket and communicate with the server. The server is usually the only side of the connection that needs a standard, fixed port. The UdpClient.Receive() method will populate the IPEndPoint with the ip/port of the sender of the packet so that you can reply to it.
Either don't bind to IPAddress.Any (that causes it to bind to all interfaces). Replace the Any with a specific IP address (one machine can have multiple if you setup IP aliasing or multiple adapters), or simpler, change the port number of the client to differ from the server. You should be able to bind one end to the primary ethernet interface IP address, and bind the client to the loopback (127.0.0.1) address.
Even though this is an old question, I think it would be good to point out an exception to the one port rule.
If you are using multicast (which is UDP to a multicast address), you can set the SO_REUSEADDR option to use the port for multiple sockets.

Tcp Hole Punching in c# using ReuseAddress

I am trying to accomplish Tcp hole punching with socket option as reuse address.
First step- Run and tcp listener in server S with active open tcp port 8001.
Second step- Run a Tcp socket with reuse address(method name is enableReuseAddres(Socket sck) mentioned below) in socket option on client A which is behind the NAT on port 8001.
Third step- Connect A => S.
Fourth step- Send data from A => S and get confirm data from S => A.
Fifth step- Get remote endpoint of A which is X.X.X.X:8001(External IP and Port of A).
Sixth Step- Listen on a socket with port 8001(method name is runServer mentioned below),in client A with reuse address(method name is enableReuseAddres(Socket sck) mentioned below) in socket option.
Disclaimer:- No error found and able to bind the same endpoint which is used to connect to the server S with the help of ReuseAddress and able to listen on the same port 8001.
But when I try to check the port 8001 is opened or closed I always get port is closed,of client A.
public void runServer()
{
Socket sk = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
enableReuseAddres(sk);
sk.Bind(loclEP);
sk.Listen(1);
var connection_socket = sk.Accept();
MessageBox.Show("Connected");
}
IPEndPoint loclEP = new IPEndPoint(IPAddress.Any, 8001);
public void enableReuseAddres(Socket sck)
{
sck.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress, true);
sck.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.KeepAlive, true);
}

Close a socket and then reopen it from the same port in .net

Well, I wonder if some one can help with a problem that I encounter....
I want to close a socket and then rerun from the same port. This is what i am doing...
opening:
UdpServer = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
UdpServerIpEndPoint = new IPEndPoint(IPAddress.Any, 9050);
UdpEndPoint = (EndPoint)UdpServerIpEndPoint;
UdpServer.Bind(UdpServerIpEndPoint);
closeing:
UdpServer.Shutdown(SocketShutdown.Both);
UdpServer.Disconnect(true);
UdpServer.Close();
After I close it. and the I try to reconnect it with the same code as above, I get error:
Additional information: Only one usage of each socket address
(protocol/network address/port) is normally permitted
I checked for exception during closing, but I didnt get any, i guessed they were closed properly, so actually, what is causing this problem? Please help!
I got answer....
I need to use this after decleration of socket...
socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress, true);
You could look at this 2 ways.
Don't actually Receive whilst your are in your stopped state, just in your BeginReceive, just drop/ignore the data
If you really need to recreate the socket, then don't perform the disconnect on your Server because you haven't actually got a connection. Your disconnect is throwing
System.Net.Sockets.SocketException (0x80004005): A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
For reference, in case anyone else stumbles onto this question but looking for the UdpClient implementation.
int port = 1234;
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
var endPoint = new IPEndPoint(IPAddress.Any, port);
socket.Bind(endPoint);
var updClient = new UdpClient();
updClient.Client = socket;
updClient.Connect(_ipAddress, port);

How to ensure of Socket sent data?

In .NET CF on a Windows CE 5.0 based POS device, if no connection (GPRS/WiFi) is available, when i try to connect my socket object i don't get any exceptions, even after it, when i try to send bytes to somewhere by Socket.SentTo() method i don't get any exceptions too! And even the returned value indicating the size of totally sent bytes is correct! what's the matter? how can i ensure of the health of the operations?
pieces of my code:
Socket m_socClient = new Socket(
AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAdd = IPAddress.Parse("192.168.7.80");
IPEndPoint remoteEP = new IPEndPoint(ipAdd, 2415);
m_socClient.Connect(remoteEP); // No exception!
// why works?
int iSent = m_socClient.SendTo(byData, byData.Length,
SocketFlags.None, remoteEP);
Few suggestions:
Check the Connected property of the connection
I understand SendTo is more suited for connectionless protocols, and Send() is better suited for Connection-oriented protocols like TCP.
Send() (and I expect SendTo()) may have no effect if there is no data to send. Have you checked there is data?

Categories

Resources