Asynchronous socket problem

M

Matthew Groch

To All Networking/.NET/C# gurus out there:

Can anyone explain the behavior of what's happening under the covers
when the following client intereacts with the following server (code
below)? This code is basically a stripped down version of a system I'm
trying to put together that is having major stability issues.

Basically, the client connects to the server and starts pouring
information onto the socket connection in an asynchronous fashion. The
server takes it's time processing the information it receives off of
the socket connection. Eventually, the whole thing blows up... and
when it blows up, I mean until I kill the server process, I can't use
IE anymore, instant messager dies, PCAnywhere dies, etc..

Here's the exception that gets thrown server side:

Unhandled Exception: System.InvalidOperationException: AcceptCallback
---> Syste
m.Net.Sockets.SocketException: An operation on a socket could not be
performed b
ecause the system lacked sufficient buffer space or because a queue
was full
at System.Net.Sockets.Socket.BeginSend(Byte[] buffer, Int32 offset,
Int32 siz
e, SocketFlags socketFlags, AsyncCallback callback, Object state)
at Server.Server.HandleSocketAccept(IAsyncResult result) in
v:\socketbuffer\s
erver\class1.cs:line 65
at System.Net.Sockets.AcceptAsyncResult.AcceptCallback(Object
stateObject, Bo
olean Signaled)
--- End of inner exception stack trace ---
at System.Net.Sockets.AcceptAsyncResult.AcceptCallback(Object
stateObject, Bo
olean Signaled)


And, here's the code:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Server
{
public class Server
{
private AsyncCallback _acceptCallback;

private AsyncCallback _acceptSend;

private Socket _socket;

private byte[] _message;

public Server(int port)
{
string str = "aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg"
+
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg";

Encoding encoding = Encoding.GetEncoding("iso-8859-1");
_message = encoding.GetBytes(str);

_acceptCallback = new AsyncCallback(this.HandleSocketAccept);
_acceptSend = new AsyncCallback(this.HandleSendData);

_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
_socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress,1);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any,port);
_socket.Bind(endPoint);
_socket.Listen(1);
_socket.BeginAccept(_acceptCallback,_socket);
}

private void HandleSocketAccept(IAsyncResult result)
{
Socket server = (Socket)result.AsyncState;
Socket socket = server.EndAccept(result);

// start test
while (true)
{
socket.BeginSend(_message,0,_message.Length,SocketFlags.None,_acceptSend,socket);
Console.WriteLine("Sent msg!");
}
}

private void HandleSendData(IAsyncResult result)
{
Socket socket = null;

try
{
socket = (Socket)result.AsyncState;
int numBytes = socket.EndSend(result);
Console.WriteLine("wrote " + numBytes + " bytes!");
}

catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}

public class Class1
{
public static void Main(string[] args)
{
try
{
Server server = new Server(6969);
Console.WriteLine("Listening!");
Console.ReadLine();
}

catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Client
{
public class Client
{
private AsyncCallback _acceptReceive;

private Socket _socket;

private byte[] _buffer;

public Client(int port)
{
_buffer = new byte[1024];
_acceptReceive = new AsyncCallback(this.HandleReceiveData);
_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
_socket.Connect(new
IPEndPoint(Dns.Resolve("localhost").AddressList[0],port));
_socket.BeginReceive(_buffer,0,_buffer.Length,SocketFlags.None,_acceptReceive,_socket);
}

private void HandleReceiveData(IAsyncResult result)
{
Socket socket = null;

try
{
socket = (Socket)result.AsyncState;
int numBytes = socket.EndReceive(result);

if (numBytes > 0)
{
Console.Write(".");
Thread.Sleep(1000);
}
}

catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}

class Class1
{
public static void Main(string[] args)
{
Client client = new Client(6969);
Console.WriteLine("Client started!");
Console.ReadLine();
}
}
}
 
A

Adam W Root

You've got your concepts mixed up. You are sending data too fast. The code
you wrote is sending code in a fashion that SHOULD be synchronous, but you
do it using asynchronous method calls. Here's some pseudocode:

mymethod()
{
BeginSend();
// now do something else!! you won't be held up by the previous call
}

mysendcallback()
{
EndSend();
if (more data to send) BeginSend();
}

Hope this helps, I know it's vague, but it gives you the idea. Basically,
you were trying to send, then send more before that send completed, then
send more before either send completed, etc etc...

It worked for awhile, because the buffer slowly got more and more full, then
it filled and crashed.

Good luck

Adam

Matthew Groch said:
To All Networking/.NET/C# gurus out there:

Can anyone explain the behavior of what's happening under the covers
when the following client intereacts with the following server (code
below)? This code is basically a stripped down version of a system I'm
trying to put together that is having major stability issues.

Basically, the client connects to the server and starts pouring
information onto the socket connection in an asynchronous fashion. The
server takes it's time processing the information it receives off of
the socket connection. Eventually, the whole thing blows up... and
when it blows up, I mean until I kill the server process, I can't use
IE anymore, instant messager dies, PCAnywhere dies, etc..

Here's the exception that gets thrown server side:

Unhandled Exception: System.InvalidOperationException: AcceptCallback
---> Syste
m.Net.Sockets.SocketException: An operation on a socket could not be
performed b
ecause the system lacked sufficient buffer space or because a queue
was full
at System.Net.Sockets.Socket.BeginSend(Byte[] buffer, Int32 offset,
Int32 siz
e, SocketFlags socketFlags, AsyncCallback callback, Object state)
at Server.Server.HandleSocketAccept(IAsyncResult result) in
v:\socketbuffer\s
erver\class1.cs:line 65
at System.Net.Sockets.AcceptAsyncResult.AcceptCallback(Object
stateObject, Bo
olean Signaled)
--- End of inner exception stack trace ---
at System.Net.Sockets.AcceptAsyncResult.AcceptCallback(Object
stateObject, Bo
olean Signaled)


And, here's the code:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Server
{
public class Server
{
private AsyncCallback _acceptCallback;

private AsyncCallback _acceptSend;

private Socket _socket;

private byte[] _message;

public Server(int port)
{
string str = "aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg"
+
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg";

Encoding encoding = Encoding.GetEncoding("iso-8859-1");
_message = encoding.GetBytes(str);

_acceptCallback = new AsyncCallback(this.HandleSocketAccept);
_acceptSend = new AsyncCallback(this.HandleSendData);

_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);_socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddre
ss,1);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any,port);
_socket.Bind(endPoint);
_socket.Listen(1);
_socket.BeginAccept(_acceptCallback,_socket);
}

private void HandleSocketAccept(IAsyncResult result)
{
Socket server = (Socket)result.AsyncState;
Socket socket = server.EndAccept(result);

// start test
while (true)
{
socket.BeginSend(_message,0,_message.Length,SocketFlags.None,_acceptSend,soc
ket);
Console.WriteLine("Sent msg!");
}
}

private void HandleSendData(IAsyncResult result)
{
Socket socket = null;

try
{
socket = (Socket)result.AsyncState;
int numBytes = socket.EndSend(result);
Console.WriteLine("wrote " + numBytes + " bytes!");
}

catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}

public class Class1
{
public static void Main(string[] args)
{
try
{
Server server = new Server(6969);
Console.WriteLine("Listening!");
Console.ReadLine();
}

catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Client
{
public class Client
{
private AsyncCallback _acceptReceive;

private Socket _socket;

private byte[] _buffer;

public Client(int port)
{
_buffer = new byte[1024];
_acceptReceive = new AsyncCallback(this.HandleReceiveData);
_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
_socket.Connect(new
IPEndPoint(Dns.Resolve("localhost").AddressList[0],port));
_socket.BeginReceive(_buffer,0,_buffer.Length,SocketFlags.None,_acceptReceiv
e,_socket);
}

private void HandleReceiveData(IAsyncResult result)
{
Socket socket = null;

try
{
socket = (Socket)result.AsyncState;
int numBytes = socket.EndReceive(result);

if (numBytes > 0)
{
Console.Write(".");
Thread.Sleep(1000);
}
}

catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}

class Class1
{
public static void Main(string[] args)
{
Client client = new Client(6969);
Console.WriteLine("Client started!");
Console.ReadLine();
}
}
}
 
J

Jared Parsons [MSFT]

The basic problem here is that your server class is sending data and the
client is not processing it. You'll notice that you're class Client only
post a single BeginReceive(). After the first receive, it won't process any
more data.

However your class Server is sending data at an extremely fast rate to the
client and it is not waiting for confirmation inbetween sends. Eventually
the data sent by the server will fill up the kernel buffer's on the client
computer and then it will start backing up on the server computer.
Eventually an error will get produced.

I'm not sure why the error is being thrown where it is though.

You have several options to prevent this error from occuring.
1) Don't send in a loop in the server. Instead send one time when the
socket is accepted. Then in the EndSend call back, send your data again.
This will prevent you from overflowing the buffers on the server.
2) Receive more than once in the client.

This problem you're seeing is partly associated with the internal workings
of BeginReceive/EndReceive and BeginSend/EndSend. Under the hood, I believe
these methods use I/O Completion ports. If you're curious about how that
works take a look at this article.

http://msdn.microsoft.com/msdnmag/issues/1000/Winsock/

Please post back if can't get around this problem

--
Jared Parsons [MSFT]
(e-mail address removed)
This posting is provided "AS IS" with no warranties, and confers no rights.
OR if you wish to include a script sample in your post please add "Use of
included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm"

Matthew Groch said:
To All Networking/.NET/C# gurus out there:

Can anyone explain the behavior of what's happening under the covers
when the following client intereacts with the following server (code
below)? This code is basically a stripped down version of a system I'm
trying to put together that is having major stability issues.

Basically, the client connects to the server and starts pouring
information onto the socket connection in an asynchronous fashion. The
server takes it's time processing the information it receives off of
the socket connection. Eventually, the whole thing blows up... and
when it blows up, I mean until I kill the server process, I can't use
IE anymore, instant messager dies, PCAnywhere dies, etc..

Here's the exception that gets thrown server side:

Unhandled Exception: System.InvalidOperationException: AcceptCallback
---> Syste
m.Net.Sockets.SocketException: An operation on a socket could not be
performed b
ecause the system lacked sufficient buffer space or because a queue
was full
at System.Net.Sockets.Socket.BeginSend(Byte[] buffer, Int32 offset,
Int32 siz
e, SocketFlags socketFlags, AsyncCallback callback, Object state)
at Server.Server.HandleSocketAccept(IAsyncResult result) in
v:\socketbuffer\s
erver\class1.cs:line 65
at System.Net.Sockets.AcceptAsyncResult.AcceptCallback(Object
stateObject, Bo
olean Signaled)
--- End of inner exception stack trace ---
at System.Net.Sockets.AcceptAsyncResult.AcceptCallback(Object
stateObject, Bo
olean Signaled)


And, here's the code:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Server
{
public class Server
{
private AsyncCallback _acceptCallback;

private AsyncCallback _acceptSend;

private Socket _socket;

private byte[] _message;

public Server(int port)
{
string str = "aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg"
+
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg";

Encoding encoding = Encoding.GetEncoding("iso-8859-1");
_message = encoding.GetBytes(str);

_acceptCallback = new AsyncCallback(this.HandleSocketAccept);
_acceptSend = new AsyncCallback(this.HandleSendData);

_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);_socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddre
ss,1);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any,port);
_socket.Bind(endPoint);
_socket.Listen(1);
_socket.BeginAccept(_acceptCallback,_socket);
}

private void HandleSocketAccept(IAsyncResult result)
{
Socket server = (Socket)result.AsyncState;
Socket socket = server.EndAccept(result);

// start test
while (true)
{
socket.BeginSend(_message,0,_message.Length,SocketFlags.None,_acceptSend,soc
ket);
Console.WriteLine("Sent msg!");
}
}

private void HandleSendData(IAsyncResult result)
{
Socket socket = null;

try
{
socket = (Socket)result.AsyncState;
int numBytes = socket.EndSend(result);
Console.WriteLine("wrote " + numBytes + " bytes!");
}

catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}

public class Class1
{
public static void Main(string[] args)
{
try
{
Server server = new Server(6969);
Console.WriteLine("Listening!");
Console.ReadLine();
}

catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Client
{
public class Client
{
private AsyncCallback _acceptReceive;

private Socket _socket;

private byte[] _buffer;

public Client(int port)
{
_buffer = new byte[1024];
_acceptReceive = new AsyncCallback(this.HandleReceiveData);
_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
_socket.Connect(new
IPEndPoint(Dns.Resolve("localhost").AddressList[0],port));
_socket.BeginReceive(_buffer,0,_buffer.Length,SocketFlags.None,_acceptReceiv
e,_socket);
}

private void HandleReceiveData(IAsyncResult result)
{
Socket socket = null;

try
{
socket = (Socket)result.AsyncState;
int numBytes = socket.EndReceive(result);

if (numBytes > 0)
{
Console.Write(".");
Thread.Sleep(1000);
}
}

catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}

class Class1
{
public static void Main(string[] args)
{
Client client = new Client(6969);
Console.WriteLine("Client started!");
Console.ReadLine();
}
}
}
 
M

Matthew Groch

Sorry, I should have pointed out in my previous post that I
deliberately had the client not receive any more data after the first
receive in order to reach the breakdown point more quickly. The
example code I provided is definitely a contrived replica of the issue
I'm working with.

In real life, I have multiple legacy front-end applications that
receive high volumes of data from a single server. These front-end
apps tend to process their incoming socket data slowly (they have to
parse it before processing, etc..) Meanwhile, the server is receiving
a high-volume data stream from a 3rd-party source and simply trying to
broadcast it out to these clients as fast as it receives it.
Eventually after some time (depending on the rate of the 3rd-party
data stream), the server bombs out with the condition I describe in my
previous post.

I am not very familiar with the front-end clients- in fact, I'm not
for sure if they receive data off their socket connections in a
synchronous or asynchronous fashion (I must investigate this). But,
I'm under the belief that the fundamentals are the same: If the rate
of sends on the socket is greater than the rate of receives on the
socket (consistently, over a long enough period of time), then my
current system will break.

I'll go ahead and follow up on that link you provided, Jared
(thanks!). My end goal is to ensure that I can avoid the buffer
overflow; ideally using asynchronous sockets. Any futher suggestions
toward the point would be GREATLY appreciated. Thanks in advance-



Jared Parsons said:
The basic problem here is that your server class is sending data and the
client is not processing it. You'll notice that you're class Client only
post a single BeginReceive(). After the first receive, it won't process any
more data.

However your class Server is sending data at an extremely fast rate to the
client and it is not waiting for confirmation inbetween sends. Eventually
the data sent by the server will fill up the kernel buffer's on the client
computer and then it will start backing up on the server computer.
Eventually an error will get produced.

I'm not sure why the error is being thrown where it is though.

You have several options to prevent this error from occuring.
1) Don't send in a loop in the server. Instead send one time when the
socket is accepted. Then in the EndSend call back, send your data again.
This will prevent you from overflowing the buffers on the server.
2) Receive more than once in the client.

This problem you're seeing is partly associated with the internal workings
of BeginReceive/EndReceive and BeginSend/EndSend. Under the hood, I believe
these methods use I/O Completion ports. If you're curious about how that
works take a look at this article.

http://msdn.microsoft.com/msdnmag/issues/1000/Winsock/

Please post back if can't get around this problem

--
Jared Parsons [MSFT]
(e-mail address removed)
This posting is provided "AS IS" with no warranties, and confers no rights.
OR if you wish to include a script sample in your post please add "Use of
included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm"

Matthew Groch said:
To All Networking/.NET/C# gurus out there:

Can anyone explain the behavior of what's happening under the covers
when the following client intereacts with the following server (code
below)? This code is basically a stripped down version of a system I'm
trying to put together that is having major stability issues.

Basically, the client connects to the server and starts pouring
information onto the socket connection in an asynchronous fashion. The
server takes it's time processing the information it receives off of
the socket connection. Eventually, the whole thing blows up... and
when it blows up, I mean until I kill the server process, I can't use
IE anymore, instant messager dies, PCAnywhere dies, etc..

Here's the exception that gets thrown server side:

Unhandled Exception: System.InvalidOperationException: AcceptCallback
---> Syste
m.Net.Sockets.SocketException: An operation on a socket could not be
performed b
ecause the system lacked sufficient buffer space or because a queue
was full
at System.Net.Sockets.Socket.BeginSend(Byte[] buffer, Int32 offset,
Int32 siz
e, SocketFlags socketFlags, AsyncCallback callback, Object state)
at Server.Server.HandleSocketAccept(IAsyncResult result) in
v:\socketbuffer\s
erver\class1.cs:line 65
at System.Net.Sockets.AcceptAsyncResult.AcceptCallback(Object
stateObject, Bo
olean Signaled)
--- End of inner exception stack trace ---
at System.Net.Sockets.AcceptAsyncResult.AcceptCallback(Object
stateObject, Bo
olean Signaled)


And, here's the code:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Server
{
public class Server
{
private AsyncCallback _acceptCallback;

private AsyncCallback _acceptSend;

private Socket _socket;

private byte[] _message;

public Server(int port)
{
string str = "aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg"
+
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg" +
"aldgh;elskghlskhglsghlshg;slghl;sgha;lgh;lahg;lshg;lshg;lshg";

Encoding encoding = Encoding.GetEncoding("iso-8859-1");
_message = encoding.GetBytes(str);

_acceptCallback = new AsyncCallback(this.HandleSocketAccept);
_acceptSend = new AsyncCallback(this.HandleSendData);

_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);_socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddre
ss,1);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any,port);
_socket.Bind(endPoint);
_socket.Listen(1);
_socket.BeginAccept(_acceptCallback,_socket);
}

private void HandleSocketAccept(IAsyncResult result)
{
Socket server = (Socket)result.AsyncState;
Socket socket = server.EndAccept(result);

// start test
while (true)
{
socket.BeginSend(_message,0,_message.Length,SocketFlags.None,_acceptSend,soc
ket);
Console.WriteLine("Sent msg!");
}
}

private void HandleSendData(IAsyncResult result)
{
Socket socket = null;

try
{
socket = (Socket)result.AsyncState;
int numBytes = socket.EndSend(result);
Console.WriteLine("wrote " + numBytes + " bytes!");
}

catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}

public class Class1
{
public static void Main(string[] args)
{
try
{
Server server = new Server(6969);
Console.WriteLine("Listening!");
Console.ReadLine();
}

catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Client
{
public class Client
{
private AsyncCallback _acceptReceive;

private Socket _socket;

private byte[] _buffer;

public Client(int port)
{
_buffer = new byte[1024];
_acceptReceive = new AsyncCallback(this.HandleReceiveData);
_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
_socket.Connect(new
IPEndPoint(Dns.Resolve("localhost").AddressList[0],port));
_socket.BeginReceive(_buffer,0,_buffer.Length,SocketFlags.None,_acceptReceiv
e,_socket);
}

private void HandleReceiveData(IAsyncResult result)
{
Socket socket = null;

try
{
socket = (Socket)result.AsyncState;
int numBytes = socket.EndReceive(result);

if (numBytes > 0)
{
Console.Write(".");
Thread.Sleep(1000);
}
}

catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}

class Class1
{
public static void Main(string[] args)
{
Client client = new Client(6969);
Console.WriteLine("Client started!");
Console.ReadLine();
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top