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.
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
I am making a program that starts a child process and communicates via anonymous pipes. When I read from a pipe, the program hangs at the first ReadLine() call as seen in the following code method:
// Reads messages sent from module's process via anonymous pipe
internal string[] ReadPipe() {
try {
Log.Verbose("Checking read pipe");
// Check for sync message and return null if there is no message to receive
string pipeMessage = _pipeInReader.ReadLine(); // HANGS ON THIS LINE
if(pipeMessage == null || !pipeMessage.StartsWith("SYNC")) {
Log.Verbose("No message found in pipe");
return null;
}
// Return array of message lines
Log.Verbose("Received message from module {ModuleName}", _fileInfo.Name);
List<string> pipeMessageLines = new();
do {
pipeMessage = _pipeInReader.ReadLine();
pipeMessageLines.Add(pipeMessage);
Log.Debug(pipeMessage);
} while(pipeMessage != null && !pipeMessage.StartsWith("END"));
return pipeMessageLines.ToArray();
} catch(Exception e) {
Log.Error(e.ToString());
return null;
}
}
The code I am using to write to the pipe is the following:
// Sends a message to module's process via anonymous pipe
public static void WritePipe(string message) {
try {
Log.Verbose("Sending \"{Message}\" to kit pipe", message);
// Send sync message and wait for module process to receive it
Log.Verbose("Waiting for pipe drain");
_pipeOutWriter.Write("SYNC");
_pipeOut.WaitForPipeDrain();
// Send the specified message
Log.Verbose("Pipe drained. Sending message");
_pipeOutWriter.Write(message);
_pipeOutWriter.Write("END");
} catch(Exception e) {
Log.Error(e.ToString());
}
}
Why does it hang at that ReadLine() line?
Thanks in advance!
Without a proper minimal, reproducible example, it's impossible to say for sure. However, one glaring problem with your code is that when you write to the _pipeOutWriter object, you don't call Flush(). Assuming that's a TextWriter, by default it's going to buffer the data until the internal buffer is full, and not send anything to the underlying Stream until then.
By calling Flush(), you force it to flush its internal buffer and send the data right away.
If that does not address your question, please edit the question to improve it, making sure to provide a minimal, reproducible example, and any additional details about what you've tried so far to fix the problem and what specifically you need help with.
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.
I am trying to write a TCP client thread that will connect to a server and continue to process data as it receives it. Sometimes the client will lose connection to the server. When the connection is re-established, the thread should resume/recover and automatically start processing data again. I can't seem to get this to work. The basic algorithm is below. My problem is that I just don't quite understand how the TcpClient behaves when the network connection is lost. How can I tell that the connection has been lost? Do I then need to close the connection? How do I reestablish the connection and continue on?
TcpClient _tcpClient;
IPEndPoint _ipEndPoint;
bool _cancelled = false;
bool _error = true;
while (!_cancelled)
{
try
{
if(_error)
{
_ipEndPoint = new IPEndPoint(_myAddress, _myPort);
_tcpClient.Connect(_ipEndPoint);
_networkStream = _tcpClient.GetStream();
_error = false;
}
else
{
_data = new byte[10025];
if(_networkStream.CanRead)
{
_bytesRead = _networkStream.Read(_data, 0, (int)_tcpClient.ReceiveBufferSize);
if(_bytesRead > 0)
{
...process the data...
}
else
{
_error = true;
}
}
else
{
_error = true;
}
}
}
catch(Exception ex)
{
...log error...
_error = true;
}
}
there is a Connected property on the TcpClient, but it is only updated when a Write or Read is executed on the NetworkStream.
I think you can just execute a Read(null,0,0) or Write(null,0,0) if you want to force a connectivity check. But in the example you have you can check the Connected or CanRead properties after your _networkStream.Read is completed.
As for reestablishing the link what you have will work. I would suggest Disposing of the old network stream before getting a new one. Something like this:
if(_networkStream != null)
{
_networkStream.Dispose();
}
_networkStream = _tcpClient.GetStream();
What I do is start a reconnect timer that will attempt to reconnect on a configured interval. Depending on the TcpHost your connecting to you may even want to start trying at a small interval 500-1000ms and increment is after a given number of failed retries so your not wasting a lot of time trying to connect to a host that is gone. Then after a max number of tries just give up unless the user explicitly requests to try again. But that also depends on what else your app is doing, if the connection is its sole purpose or if its just one piece.
The wrapper class I use to interact with TcpClient is around 700 lines of code and it handles reconnects, sending data as well as reading it. I work in a closed shop so i cant post it but if you have any other specific question I'd be happy to help.
Good luck.
Hi guys i have an issue currently when using a Socket to send data.
I am currently getting a very strange issue when a Client sends to the server, for example "HEART", as a heart beat. afer sending the first time the server starts receiving a whole lot of \0, not always the same amount before the HEART. I am using queues to queue up sending so on slow connections it waits for the current send to be done before it sends the next but for tiny lengths like that i'm a bit confused.
public void Send(string data)
{
if (Connected)
{
SendQueue.Enqueue(data);
if (t.ThreadState == ThreadState.Stopped)
{
t = new Thread(new ThreadStart(SendData));
t.Start();
}
else if (t.ThreadState == ThreadState.Unstarted)
t.Start();
}
}
and the SendData function
private void SendData()
{
if (sending)
return;
sending = true;
while (SendQueue.Count > 0)
{
if (ClientSocket.Connected)
{
byte[] data = Networking.StringToByte((string)SendQueue.Dequeue());
ClientSocket.Send(data);
}
}
sending = false;
}
i don't think it's the sending function because i've debugged it and the byte array always holds the correct info.
the receiving end is even simpler.
public string Receive()
{
string msg = "";
if (Connected)
{
byte[] data = new byte[1024];
while (ClientSocket.Avaliable > 0)
{
ClientSocket.Receive(data);
msg += Networking.ByteToString(data).Trim();
}
}
return msg;
}
If anyone could point out where i'm going wrong or if i've gone at this the entirely wrong way that would be great.
Thanks guys.
I will remind people that it's seemingly random lengths of \0 each 2 seconds (in this example for the HEART message heartbeat)
This piece of code can't be correct:
byte[] data = new byte[1024];
while (ClientSocket.Avaliable > 0)
{
ClientSocket.Receive(data);
msg += Networking.ByteToString(data).Trim();
}
It seems you do not take into account how much data you actually receive. You have to look at the return value from ClientSocket.Receive I don't know what your Networking.ByteToString does but when your code runs Networking.ByteToString , that function cannot know how much data you actually received. It'll probably convert the entire buffer - all 1024 bytes. And that's likely where all your zeroes comes from. It could be that somewhere you're doing a similar thing on the sending side.
You also might need to keep in mind that TCP is stream oriented, not packet oriented. If you do 1 Send call, that can take several Receive calls to read, or 1 Receive call might read the data from many Send calls.