**i use c# this code socket connection with multi threading **
i need set time out to my socket connection telnet
string ip = "";
int port = 23;
string str = "";
IPAddress address = IPAddress.Parse(ip);
IPEndPoint ipEndPoint = new IPEndPoint(address, port);
Socket socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Connect((EndPoint)ipEndPoint);
try
{
byte[] numArray = new byte[1024];
while (socket.Connected) {
int count = socket.Receive(numArray);
str += Encoding.ASCII.GetString(numArray, 0, count);
Console.WriteLine(str);
}
socket.Close();
}
catch (ArgumentNullException ex)
{
}
You can either create a timer to do this or what I like to do is give the socket.connected a timeframe and base my connection of that. You'd obviously need to modify the time per your conditions, but this example has worked for me in the past.
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Connect using a timeout (5 seconds)
IAsyncResult result = socket.BeginConnect( iP, iPort, null, null );
bool success = result.AsyncWaitHandle.WaitOne( 5000, true );
if ( socket.Connected )
{
socket.EndConnect( result );
}
else
{
//Be sure to close socket
socket.Close();
throw new ApplicationException("Failed to connect the server. Try again.");
}
I saw another example someone else did with timer, but I have not personally used this, so whichever you are more comfortable with. start a timer (timer_connection), if time is up, check whether socket connection is connected (if(m_clientSocket.Connected)), if not, pop up timeout error
private void connect(string ipAdd,string port)
{
try
{
SocketAsyncEventArgs e=new SocketAsyncEventArgs();
m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(serverIp);
int iPortNo = System.Convert.ToInt16(serverPort);
IPEndPoint ipEnd = new IPEndPoint(ip, iPortNo);
//m_clientSocket.
e.RemoteEndPoint = ipEnd;
e.UserToken = m_clientSocket;
e.Completed+=new EventHandler<SocketAsyncEventArgs>(e_Completed);
m_clientSocket.ConnectAsync(e);
if (timer_connection != null)
{
timer_connection.Dispose();
}
else
{
timer_connection = new Timer();
}
timer_connection.Interval = 2000;
timer_connection.Tick+=new EventHandler(timer_connection_Tick);
timer_connection.Start();
}
catch (SocketException se)
{
lb_connectStatus.Text = "Connection Failed";
MessageBox.Show(se.Message);
}
}
private void e_Completed(object sender,SocketAsyncEventArgs e)
{
lb_connectStatus.Text = "Connection Established";
WaitForServerData();
}
private void timer_connection_Tick(object sender, EventArgs e)
{
if (!m_clientSocket.Connected)
{
MessageBox.Show("Connection Timeout");
//m_clientSocket = null;
timer_connection.Stop();
}
}
Related
I'm trying to save a connected socket in a dictionary so my API doesn't have to create a new connection every time. My problem is that the socket gets disposed.
So when I call GetConnection() a second time socket.connected is false and socket.Available.Message is "Cannot access a disposed object. Object name: 'System.Net.Sockets.Socket'.".
public static class ModbusSocket
{
private static Dictionary<IPAddress, Socket> socketList;
public static Socket GetConnection(string server, int port)
{
if (socketList is null)
{
socketList = new Dictionary<IPAddress, Socket>();
}
IPAddress iPAddress = IPAddress.Parse(server);
if (socketList.ContainsKey(iPAddress))
{
var socket = socketList[iPAddress];
if (socket.Connected)
{
return socket;
}
else
{
socketList.Remove(iPAddress);
socket = new Socket(iPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipe = new IPEndPoint(iPAddress, port);
socket.Connect(ipe);
socketList.Add(iPAddress, socket);
return socket;
}
}
else
{
Socket socket = new Socket(iPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipe = new IPEndPoint(iPAddress, port);
socket.Connect(ipe);
socketList.Add(iPAddress, socket);
return socket;
}
}
}
OMG I found the issue...
I invoked it with using:
using (Socket s = ModbusSocket.GetConnection(hostIp, port))
{
var telegram = new Telegram();
telegram.Set(0, AddressConst.PositionWindow, 4);
var response = telegram.SendAndReceive(s);
var result = BitConverter.ToInt32(new byte[] { response.Byte19, response.Byte20, response.Byte21, response.Byte22 }, 0);
return result;
}
I have setup a client server chat system. That will have to work on different computers. At the moment I am testing and so both client and server are on my localhost.
At the moment I focus on the client reception (with a 8192 byte buffer) for it is that the problem resides.
And the problem is that when issue a command with very short text (here 123):
Server SHORT_COMMAND 123% ---> Client SHORT_COMMAND 123%
but when I issue a very long command (24k) each single batch does not arrive in the correct order
E.g. imagine a very long text 111.....11112222....2222333....33334444....4444
LONG_COMMAND 111....3333% is therefore automatically cut into
LONG_COMMAND 111....1111
2222....2222
3333...3333
4444...4444%
and sent in that order
what is wrong is the reception and what might happen is to receive
LONG_COMMAND 111....1111
2222....2222
4444...4444%
3333...3333
or it might get mixed with other short commands like
LONG_COMMAND 111....1111
2222....2222
SHORT_COMMAND 123%
3333...3333
4444...4444%
Take into account that some messages can be sent very quickly one after the other.
Thank you for ANY help
Patrick
Client code
I start the client with the following routine. In my case I pass -1
public static bool StartClient(string strIpAddress, string strPort)
{
// Connect to a remote device.
try
{
if (strIpAddress.Trim() == "-1")
strIpAddress = GetLocalIPAddress();
IPAddress ipAddress = IPAddress.Parse(strIpAddress);
int port = int.Parse(strPort);
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { NoDelay = true };
socketClient.BeginConnect(remoteEP, new AsyncCallback(ConnectClientCallback), socketClient);
OnNotification_Client?.Invoke(eSocketOperation.CONNECT, "Client connected to " + strIpAddress + " port=" + strPort, eSocketOperationResultType.SUCCESS);
ReceiveClient();
return true;
}
catch (Exception e)
{
MessageBox.Show("StartClient exc:" + e.ToString());
return false;
}
}
then
private static void ConnectClientCallback(IAsyncResult ar)
{
try
{
socketClient = (Socket)ar.AsyncState;
socketClient.EndConnect(ar);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
The following part is the reception with:
public static void ReceiveClient()
{
try
{
StateObject state = new StateObject();
state.workSocket = socketClient;
socketClient.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback_Client), state);
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "ReceiveClient", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
finally
private static void ReceiveCallback_Client(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
if (!client.Connected)
return;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
string message = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
if (message == null)
OnNotification_Client?.Invoke(eSocketOperationResultType.ERROR, "Received null message from server", eSocketOperationResultType.ERROR);
else
{
strReceivedMessageClient += message;
if (strReceivedMessageClient.EndsWith(StateObject.CONFIRMATION.ToString()))
{
...
Server Code
The server is started with
public static void StartServer(string _strPort)
{
Serializers.Logger.WriteLog("StartServer");
StrPort = _strPort;
// Data buffer for incoming data.
byte[] bytes = new Byte[BufferSize];
IPAddress ipAddress = IPAddress.Parse(GetLocalIPAddress());
int port = int.Parse(_strPort);
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
if (listener == null)
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
OnNotification_Server?.Invoke("Waiting for a connection on " + ipAddress.ToString());
listener.BeginAccept(new AsyncCallback(AcceptCallbackServer), listener);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
Accept
public static void AcceptCallbackServer(IAsyncResult ar)
{
if (listener == null)
return;
listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback_Server), state);
}
and last but not least the send:
public static void SendFromServerToClient(object command, String data, eSocketOperationResultType sort)
{
string strMessage; ;
strMessage = command.ToString() + '|' + data + '|' + sort + "%";
byte[] byteData = Encoding.ASCII.GetBytes(strMessage);
try
{
if (socketServer != null)
socketServer.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), socketServer);
}
catch (Exception exc)
{
}
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
I created two projects one with client and other with server to exchange text between both of them;on same computer i run those exe.
MY Client Side Connection Code connection looked :
using (SocketClient sa = new SocketClient(host, port))
{
sa.Connect();
Console.WriteLine(sa.SendReceive("Message #" + i.ToString()));
}
sa.Disconnect();
while socketclient is my class which contain these methods and constructor:
internal SocketClient(String hostName, Int32 port)
{
IPHostEntry host = Dns.GetHostEntry(hostName);
IPAddress[] addressList = host.AddressList;
this.hostEndPoint = new IPEndPoint(addressList[addressList.Length - 1], port);
this.clientSocket = new Socket(this.hostEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
}
internal void Connect()
{
SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();
connectArgs.UserToken = this.clientSocket;
connectArgs.RemoteEndPoint = this.hostEndPoint;
connectArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect);
clientSocket.ConnectAsync(connectArgs);
autoConnectEvent.WaitOne();
SocketError errorCode = connectArgs.SocketError;
if (errorCode != SocketError.Success)
{
throw new SocketException((Int32)errorCode);
}
}
internal void Disconnect()
{
clientSocket.Disconnect(false);
}
private void OnConnect(object sender, SocketAsyncEventArgs e)
{
autoConnectEvent.Set();
this.connected = (e.SocketError == SocketError.Success);
}
internal String SendReceive(String message)
{
if (this.connected)
{
Byte[] sendBuffer = Encoding.ASCII.GetBytes(message);
SocketAsyncEventArgs completeArgs = new SocketAsyncEventArgs();
completeArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length);
completeArgs.UserToken = this.clientSocket;
completeArgs.RemoteEndPoint = this.hostEndPoint;
completeArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);
clientSocket.SendAsync(completeArgs);
AutoResetEvent.WaitAll(autoSendReceiveEvents);
return Encoding.ASCII.GetString(completeArgs.Buffer, completeArgs.Offset,completeArgs.BytesTransferred);
}
else
{
throw new SocketException((Int32)SocketError.NotConnected);
}
}
while on server side code looks like that:
SocketListener sl = new SocketListener(numConnections, bufferSize);
sl.Start(port);
Console.WriteLine("Server listening on port {0}.
Press any key to terminate the server process...", port);
Console.Read();
sl.Stop();
Socket listener is my class which contain this method and constructor :
internal SocketListener(Int32 numConnections, Int32 bufferSize)
{
this.numConnectedSockets = 0;
this.numConnections = numConnections;
this.bufferSize = bufferSize;
this.readWritePool = new SocketAsyncEventArgsPool(numConnections);
this.semaphoreAcceptedClients = new Semaphore(numConnections, numConnections);
for (Int32 i = 0; i < this.numConnections; i++)
{
SocketAsyncEventArgs readWriteEventArg = new SocketAsyncEventArgs();
readWriteEventArg.Completed += new EventHandler<SocketAsyncEventArgs> (OnIOCompleted);
readWriteEventArg.SetBuffer(new Byte[this.bufferSize], 0, this.bufferSize);
this.readWritePool.Push(readWriteEventArg);
}
}
internal void Start(Int32 port)
{
IPAddress[] addressList = Dns.GetHostEntry(Environment.MachineName).AddressList;
IPEndPoint localEndPoint = new IPEndPoint(addressList[addressList.Length - 1], port);
this.listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.listenSocket.ReceiveBufferSize = this.bufferSize;
this.listenSocket.SendBufferSize = this.bufferSize;
if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
{
this.listenSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
this.listenSocket.Bind(new IPEndPoint(IPAddress.IPv6Any, localEndPoint.Port));
}
else
{
this.listenSocket.Bind(localEndPoint);
}
this.listenSocket.Listen(this.numConnections);
this.StartAccept(null);
mutex.WaitOne();
}
I have already port forward of my router because of server side exe which didn't listen without port forwarding.
it is working fine with send and receive on same pc and same port at home.
While when i try to run both of codes exe on my office computer it throws exception at following line:
Exception thrown by socket
Could any one guide me whats the problem and how to resolve it ?
Thanks
Have you tried temporary disable your Windows firewall ?
I am trying to make a program in witch multiply clients will connect to the server. But i have a problem because when i try to connect more than 1 client at the same time, it takes a "long time" to do it.
i am using asynchronous way to connect:
public bool connect(string IP,int port)
{
try
{
if (m_clientSocket == null)
{
m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(IP.ToString());
int iPortNo = System.Convert.ToInt16(port.ToString());
IPEndPoint ipEnd = new IPEndPoint(ip, iPortNo);
client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
}
}catch()
{
return false;
}
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
if (m_clientSocket != null)
{
if (m_clientSocket.Connected)
{
client.EndConnect(ar);
// send next data here
}
else
{
client.EndConnect(ar);
m_clientSocket.Close();
m_clientSocket = null;
state = CONNECT_ERROR;
}
}
}
catch ()
{
}
}
For each client I want to connect I open a new class that includes two methods that you can see above. than with simple for loop I call methods one after another.
in Wireshark I observe the time that next needs to connect to a server is 0.1s witch I think is allot.
Any idea why does it take so long ?
Thanks for any kind of help.
I am trying to establish a communication between a handheld and a PC.
I have the following code, for the client:
public void connect(string IPAddress, int port)
{
// Connect to a remote device.
try
{
IPAddress ipAddress = new IPAddress(new byte[] { 192, 168, 1, 10 });
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
if (connectDone.WaitOne()){
//do something..
}
else{
MessageBox.Show("TIMEOUT on WaitOne");
}
}
catch(Exception e){
MessageBox.Show(e.Message);
}
}
My problem is that when I run both of them in a pc they communicate fine, but the same code in a SmartDevice Project doesn't connect with the Server which is running on the PC and it give me this error:
System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or stablished connection failed
because connected host has failed to respond
What am I missing?
NOTE: The IPAddress is hard coded inside the code
EDIT: here is another code which I take from a MSDN example. This don't work either, it says that it not possible to read. The server code in this case is the same as the example, the client code have a modification:
private void button1_Click(object sender, EventArgs e)
{
// In this code example, use a hard-coded
// IP address and message.
string serverIP = "192.168.1.10";//HERE IS THE DIFERENCE
string message = "Hello";
Connect(serverIP, message);
}
Thanks in advance for any help!
For my "mobile device" client, I send data to the "PC" host using this:
private void Send(string value) {
byte[] data = Encoding.ASCII.GetBytes(value);
try {
using (TcpClient client = new TcpClient(txtIPAddress.Text, 8000)) {
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
}
} catch (Exception err) {
// Log the error
}
}
For the host, you're best to use a thread or BackgroundWorker where you can let a TcpListener object sit and wait:
private void Worker_TcpListener(object sender, DoWorkEventArgs e) {
BackgroundWorker worker = (BackgroundWorker)sender;
do {
string eMsg = null;
int port = 8000;
try {
_listener = new TcpListener(IPAddress.Any, port);
_listener.Start();
TcpClient client = _listener.AcceptTcpClient(); // waits until data is avaiable
int MAX = client.ReceiveBufferSize;
NetworkStream stream = client.GetStream();
Byte[] buffer = new Byte[MAX];
int len = stream.Read(buffer, 0, MAX);
if (0 < len) {
string data = Encoding.UTF8.GetString(buffer);
worker.ReportProgress(len, data.Substring(0, len));
}
stream.Close();
client.Close();
} catch (Exception err) {
// Log your error
}
if (!String.IsNullOrEmpty(eMsg)) {
worker.ReportProgress(0, eMsg);
}
} while (!worker.CancellationPending);
}