I am using a library on Github to connect to a server, since I am not familiar with sockets in C#. The syntax for making a connection is just:
Connector con = new Connector(ip, port, cipher);
con.Connect();
The cipher parameter is just form of encryption that the server uses and is irrelevant for my question, I think.
After I call the Connect() method the library makes an asynchronized socked and I am not quite sure what happens after that. My question is that frequently when I build my application and try to connect to the server, I get disconnected on the first attempt only. Then if I try to connect again the program works fine. I was able to trace the source of the problem to the callback method of socket.BeginReceive here:
private void Receive() {
if (m_connected) {
var error = SocketError.Success;
m_socket.BeginReceive(m_recvBuffer, 0, ReceiveSize, SocketFlags.None, out error, PacketCallback, null);
if (error != SocketError.Success) {
Disconnect();
}
}
}
private void PacketCallback(IAsyncResult iar) {
if (m_connected) {
var error = SocketError.Success;
int length = m_socket.EndReceive(iar, out error);
if (length == 0 || error != SocketError.Success) {
Disconnect();
}
else {
Append(length);
ManipulateBuffer();
Receive();
}
}
}
socket.EndReceive is returning a length of 0 which is causing the program to disconnect with SocketError.ConnectionReset. I just can't seem to figure out why it is only happening only on my first connection attempt. Every subsequent connection attempt works fine. Can someone who is familiar with sockets can tell me if it is an error in the library code, and a fix? If not, I would just have to assume it is an error on the server-side end. Thanks.
Don't use socket helpers. Socket is very easy to use in .net.
Take a look at this msdn example :https://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx
Use the code in the above link. Hope it will work for you.
Related
I'm working on a C# TCP socket based application, based on the technology from the System.Net.Sockets package.
Receiving packets goes as follows:
private void OnReceivedData(IAsyncResult ar)
{
// Socket was the passed in object
var sock = (Socket)ar.AsyncState;
// Check if we got any data
try
{
int nBytesRec = sock.EndReceive(ar);
...
When too many data get sent, parts of it are getting lost.
I remember having worked with "Computer Management", "Services and Applications", "Message Queuing", ..., but I don't remember what it was all about.
Does anybody know how I can detect and solve such apparent buffer overflooding situations?
Edit First attempt
I just tried following way to catch the issue:
SocketError socket_ErrorCode;
int nBytesRec = sock.EndReceive(ar, out socket_ErrorCode);
if (socket_ErrorCode != 0)
{
Log.Error($"Following socket errorcode is found: [{socket_ErrorCode}]");
}
=> Although again some packets were lost, that error was not shown.
Thanks in advance
Im trying to follow this code sample from microsoft, who is a basic code for sending/receiving data over network from windows 10 computer/phone.
Im on VS2015, i have a phone on W10 and my computer also.
The problem is that my application seems to create packet and send one to establish the connection (i have seen this packet with wireshark), but i never received it on the server side.
Here is code to listen port from the actual internet connection available and wait for a connection :
public static async void StartServer()
{
try
{
StreamSocketListener listener = new StreamSocketListener();
//ConnectionProfile internetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();
//await listener.BindServiceNameAsync("5043", SocketProtectionLevel.PlainSocket, internetConnectionProfile.NetworkAdapter);
listener.ConnectionReceived += OnConnection;
await listener.BindServiceNameAsync("5043");
Debug.WriteLine("Server Started !");
}
catch (Exception)
{
Debug.WriteLine("Error StartServer Method !");
}
}
The method "OnConnection" is never reach cause the event "ConnectionReceived" is never called.
Here is the code to establish connection (the string ipDestination contain the internet ip address from my phone for example, that i get from checkip.dyndns.org) :
private static StreamSocket socket;
public static async void Connect(string ipDestination)
{
try
{
//Destination Ip address
HostName host = new HostName(ipDestination);
ConnectionProfile internetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();
socket = new StreamSocket();
socket.Control.KeepAlive = true;
await socket.ConnectAsync(host, "5043");
//EXCEPTION RAISE HERE after a moment "System.Runtime.InteropServices.COMException, cant join destination.
Debug.WriteLine("Connected !");
}
catch (Exception)
{
Debug.WriteLine("Erreur Connect Method !");
}
}
I think i should miss something but i dont know why and im block at this part since a long and can't continue my project...
I apologize for the bad english I try to make my best :)
Update from comments :
As Jay Zuo suggested, i have try to use local address on private
network and it works, i can establish connection, send and receive
data without problems... So the problem come when i use internet IP
address, and i still can't figure why...
As Kiewic suggested, i have simplify my code and commented the
precedent version.
I got in trouble using ReceiveAsync().
I want to get messages from the Server.
The first message was received, however, i cannot get any message from the second.
I am still trying to find any solution, but i can't.
Part of my Client source is below :
public void Recieve_Completed(object sender, SocketAsyncEventArgs e)
{
Socket _client = (Socket)sender;
Msg _Msg = (Msg)e.UserToken;
_Msg.SetLength(e.Buffer);
_Msg.InitData();
if (_client.Connected && e.BytesTransferred > 0)
{
...
Do sth
...
_client.ReceiveAsync(e);
}
else //No Message
{
//Connection_Timer.Enabled = true;
}
}
Did I make any stupid mistake.
If then, plz let me know.
Thx in advance.
You are assuming that TCP is message-based. It is not. TCP offers you a stream of bytes. Reads can read any amount greater than zero. Your code has to deal with that fact.
I am trying to connect to my server with a TcpClient.BeginConnect / TcpClient.EndConnect combo. However, some things don't work as they should.
The scenario is as follows:
Call to the TcpClient.BeginConnect
Server is intentionally offline (for testing purposes) - thus no connection can be made.
I close the application (client.Close() gets called in the process which closes the socket which in turn stops the async operation)
TcpClient connection callback method happens giving IAsyncResult
Call to the TcpClient.EndConnect method with the given IAsyncResult
NullReferenceException happens on EndConnect (?)
Since the last form (window) was closed, the app should exit - however it does not, at least not until BeginConnect operation completes (which is strange, as callback has already been called).
What happens here is that a NullReferenceException is caught. As you can see from the picture above, neither client nor ar are null. The problem is that the MSDN documentation for the EndConnect does not mention the case in which this exception is thrown.
So basically, I have no idea what is going on. The problem is that I am forced to wait for the app to close (as if the connection operation still waits for a timeout). If a server is online, it connects and disconnects just fine.
What does NullReferenceException in this context mean? How to avoid BeginConnect operation to block the application closing in case the connection can't be established?
Additional notes (requested in comments):
Here is the code to create the client (client is a member variable:
public void Connect()
{
try
{
lock (connectionAccess)
{
if (State.IsConnectable())
{
// Create a client
client = new TcpClient();
client.LingerState = new LingerOption(false, 0);
client.NoDelay = true;
State = CommunicationState.Connecting;
client.BeginConnect(address, port, onTcpClientConnectionEstablished, null);
}
else
{
// Ignore connecting request if a connection is in a state that is not connectable
}
}
}
catch
{
Close(true);
}
}
Also the Close method:
public void Close(bool causedByError)
{
lock (connectionAccess)
{
// Close the stream
if (clientStream != null)
clientStream.Close();
// Close the gateway
if (client != null)
client.Close();
// Empty the mailboxes
incomingMailbox.Clear();
outgoingMailbox.Clear();
State = causedByError ? CommunicationState.CommunicationError : CommunicationState.Disconnected;
}
}
The NullReferenceException is probably due to TcpClient.Client being null.
If you were to follow the MSDN Example for TcpClient.BeginConnect and pass theTcpClient object as the state object:
private void onConnEst(IAsyncResult ar)
{
try
{
TcpClient client = (TcpClient)ar.AsyncState;
if(client!=null && client.Client!=null)
{
client.EndConnect(ar);
}
}
catch(Exception ex){...}
}
This should handle the case when Close() is called before the Callback.
Going back to your problem - how long does it take for the application to eventually close?
This obviously a bug inside the TcpClient class. I have also faced it. TcpClient.Dispose may set Client field to null but EndConnect does not expect that.
I had a similar error and ended up using this code. I am not sure if it will hold with the IASyncResult interface, but there may be a similar way to run this check. I do notice that your ar.AsyncState == null, so perhaps try starting there, i.e. is it null when you connect properly?
private void connConnectCompleted(AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
// Something didn't work...abort captain
CloseSocket();
Console.WriteLine(this.GetType().ToString() + #":Error connecting socket:" + e.Error.Message);
return;
}
// Do stuff with your connection
}
EDIT: Sorry I didn't realise I didn't post what generated my AsyncCompletedEventArgs, which is more related to what you are doing. You will see the reason why I was wondering as to ar.AsyncState being null.
private void OnConnect(IAsyncResult asyncResult)
{
if (OnConnectCompleted == null) return; // Check whether something is using this wrapper
AsyncCompletedEventArgs args;
try
{
Socket outSocket = (Socket) asyncResult.AsyncState;
// Complete connection
outSocket.EndConnect(asyncResult);
args = new AsyncCompletedEventArgs(null);
OnConnectCompleted(this, args);
}
catch (Exception e)
{
args = new AsyncCompletedEventArgs(e.Message);
OnConnectCompleted(this, args);
}
}
This is a know bug.
You should be receiving 'ObjectDisposedException' instead of 'NullReferenceException'.
I have written a small UDP client server class in C# that is used to provide comms between a Linux and a Windows machines.
The implementation of the UDP client and server in C# in Windows is a direct rewrite from C++ code I wrote for Linux originally.
I have no problems during run time between Linux machines but there is an intermittent problem that occasionally appears between Linux and Windows link.
Due to the application I need fast, non blocking operation of the UDP socket.
Since one client is Linux the code under C# I had to use some magic of marshalling.
Here is the code:
public bool Connect(string sIPAddr, int portNumber)
{
try
{
if (portNumber > 65535 && portNumber < 0)
{
this._isReady = false;
return this._isReady;
}
this._ipPort = portNumber;
this._ipAddress = IPAddress.Parse(sIPAddr);
IPEndPoint ipep = new IPEndPoint(this._ipAddress, this._ipPort);
this._myUDPClient = new Socket(ipep.Address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
this._myUDPClient.Blocking = false;
this._myUDPClient.Connect(this._ipAddress, this._ipPort);
this._isReady = true;
return this._isReady;
}
catch (Exception)
{
this._isReady = false;
return this._isReady;
}
}
I use connect on UDP to simplify send and receive calls.
The problem happens when I try and read from the socket.
More code:
public bool NewMessageReceived()
{
try
{
if (this._newMessaageReceived)
{
return this._newMessaageReceived;
}
else
{
_messageBuffer = new byte[65507];
int numBytesRcvd = _myUDPClient.Receive(this._messageBuffer, 65507, SocketFlags.None);
Marshal.Copy(_messageBuffer, 0, _pmessageBuffer, 65507);
if (numBytesRcvd < 0)
{
this._newMessaageReceived = false;
// TODO: Add Socket Error Checking
}
else
{
this._newMessaageReceived = true;
}
Array.Clear(_messageBuffer, 0, _messageBuffer.GetLength(0));
return this._newMessaageReceived;
}
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.Message);
return false;
}
}
I have Wireshark running on both machines and I can see that the datagram sent from Linux machine arrives on Windows machine unharmed. However the UDP client Receive call throws and exception saying: "A non-blocking socket operation could not be completed
immediately" which from what I understand is a WSAEWOULDBLOCK error. However I explicitly set blocking option to false.
The sequence of events is the following:
Windows machine sends a datagram on port 2 and listens for acknowledge on port 1. I have a while loop which implements timeout
Code:
DateTime TimeAtStart = new DateTime();
TimeAtStart = DateTime.Now;
TimeSpan TimeOut = new TimeSpan(0,0,0,0,800);
IntPtr RecievedTelPtr = new IntPtr();
bool UnpackingResult;
while (TimeOut > (DateTime.Now - TimeAtStart))
{
if (!NackAckRecieveConnection.GetIsReady())
{
ErrorEventArguements.SetAllHmiNetworkEventArgs(ID, -3, 2);
return (false);
}
if (NackAckRecieveConnection.NewMessageReceived())
{
RecievedTelPtr = NackAckRecieveConnection.GetMessage();
UnpackingResult = UnpackHmiTelegram(RecievedTelPtr, AckNackType);
NackAckRecieveConnection.MessageRetrieved();
return (UnpackingResult);
}
}
//if escape loop return timeout err msg
ErrorEventArguements.SetAllHmiNetworkEventArgs(ID, -4, (AckNackType == 0) ? (1) : (3));
return (false);
I would like to be able to understand the issue and why the problem occurs and how can I fix it as I have fun out of ideas.
Thank you
I'm not answering the question, but I do need to point out something very important:
catch (Exception)
{
this._isReady = false;
return this._isReady;
}
Do NOT hide exceptions like that. When something fails you will have no chance what so ever to try to fix it, since you will never know why something failed. Do use proper exception handling.
Due to the application I need fast, non blocking operation of the UDP socket
That statement is not correct. Non-blocking sockets are not faster, they simply return before the operation has completed.
I do recommend that you switch back to blocking sockets, since you seem to be new to socket programming. Get the application running first, then try to optimize it.
You are setting the socket that you're reading messages from to non-blocking. This instructs the socket to NOT BLOCK if the operation cannot be completed immediately. What this means in practical terms is that if you attempt to read from the socket and there is nothing waiting to be read, the call will not return successfully.
I don't know how MessageReceived is being called, however I would assume that whatever is calling it is not checking that information is actually ready to be read from the socket, prior to the call.
As you're experiencing an intermittent problem, it would suggest that most of the time, the when MessageReceived is being called, there is data to be read from the socket.
If you want to continue to use non-blocking IO, you need to either change your logic, so that it catches the IO exception and retrys after a short delay (if you're sure there's going to be data there), or check to see if there is actually data available to be read from the socket, prior to attempting to perform the read.
One way to check if there is information available on the socket (prior to attempting to read from it) would be to use Socket.Poll. Something like:
if (_myUDPClient.Poll(myTimeoutInMicroSeconds, SelectMode.SelectRead)){
// Try to read the new messsage
} else {
continue; // go back to top of loop and try again
}
You may also need to check for SelectError state, to determine if the socket has a failure. Most of my socket programming has been from C++, so I'm not sure about the .Net specifics.