Reading data on Aysnchronous socket server

G

Guest

Hi,

I have a synchronous socket server which my app uses to read data from
clients.

To test this I have a simulated client that sends 100 byte packets.

I have set up the socket server so that its buffer is bigger than this.
I did this expecting the data to be read in one pass.

However what I find is that on the first pass it only reads the first 4
bytes and then on the second pass of begin.receive, reads the rest of the
message. Is this usual?

This happens each time I send my packet from the
The code I have been using is the MSDN example( shown below).

Can anyone tell me if it is possible to read the whole message sent form the
client on the first pass rather than it taking 2 or more passes?

Thanks
Macca


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

// State object for reading client data asynchronously
public class StateObject {
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 100;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}

public class AsynchronousSocketListener {
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);

public AsynchronousSocketListener() {
}

public static void StartListening() {
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];

// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
SN.IPHostEntry ipHostInfo = SN.Dns.GetHostEntry(hostname);
SN.IPAddress ipAddress = ipHostInfo.AddressList[0];
SN.IPEndPoint localEndPoint = new SN.IPEndPoint(ipAddress, 7777);

// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );

// Bind the socket to the local endpoint and listen for incoming
connections.
try {
listener.Bind(localEndPoint);
listener.Listen(100);

while (true) {
// Set the event to nonsignaled state.
allDone.Reset();

// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener );

// Wait until a connection is made before continuing.
allDone.WaitOne();
}

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

Console.WriteLine("\nPress ENTER to continue...");
Console.Read();

}

public static void AcceptCallback(IAsyncResult ar) {
// Signal the main thread to continue.
allDone.Set();

// Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar);

// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}

public static void ReadCallback(IAsyncResult ar) {
String content = String.Empty;

// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject) ar.AsyncState;
Socket handler = state.workSocket;

// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);

if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer,0,bytesRead));

// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1) {
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content );
// Echo the data back to the client.
Send(handler, content);
} else {
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0,
StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}

private static void Send(Socket handler, String data) {
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);

// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}

private static void SendCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket handler = (Socket) ar.AsyncState;

// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);

handler.Shutdown(SocketShutdown.Both);
handler.Close();

} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
 
N

Nicholas Paldino [.NET/C# MVP]

Macca,

I don't believe it is possible. Rather, you should store the bytes that
are read in a buffer somewhere, and read again until you have the contents
of the message that you are trying to read. If you know your message is
going to be a certain length, then you can indicate how many bytes you want
to read in the call to Receive/BeginReceive. Then, when you issue the next
call, you can decrement the number of bytes you need to read.

For example, if you know your message is 100 bytes long, and the first
call to Receive/BeginReceive returns 4 bytes, then the next call can be for
96 bytes.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Macca said:
Hi,

I have a synchronous socket server which my app uses to read data from
clients.

To test this I have a simulated client that sends 100 byte packets.

I have set up the socket server so that its buffer is bigger than this.
I did this expecting the data to be read in one pass.

However what I find is that on the first pass it only reads the first 4
bytes and then on the second pass of begin.receive, reads the rest of the
message. Is this usual?

This happens each time I send my packet from the
The code I have been using is the MSDN example( shown below).

Can anyone tell me if it is possible to read the whole message sent form
the
client on the first pass rather than it taking 2 or more passes?

Thanks
Macca


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

// State object for reading client data asynchronously
public class StateObject {
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 100;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}

public class AsynchronousSocketListener {
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);

public AsynchronousSocketListener() {
}

public static void StartListening() {
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];

// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
SN.IPHostEntry ipHostInfo = SN.Dns.GetHostEntry(hostname);
SN.IPAddress ipAddress = ipHostInfo.AddressList[0];
SN.IPEndPoint localEndPoint = new SN.IPEndPoint(ipAddress,
7777);

// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );

// Bind the socket to the local endpoint and listen for incoming
connections.
try {
listener.Bind(localEndPoint);
listener.Listen(100);

while (true) {
// Set the event to nonsignaled state.
allDone.Reset();

// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener );

// Wait until a connection is made before continuing.
allDone.WaitOne();
}

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

Console.WriteLine("\nPress ENTER to continue...");
Console.Read();

}

public static void AcceptCallback(IAsyncResult ar) {
// Signal the main thread to continue.
allDone.Set();

// Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar);

// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}

public static void ReadCallback(IAsyncResult ar) {
String content = String.Empty;

// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject) ar.AsyncState;
Socket handler = state.workSocket;

// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);

if (bytesRead > 0) {
// There might be more data, so store the data received so
far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer,0,bytesRead));

// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1) {
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data :
{1}",
content.Length, content );
// Echo the data back to the client.
Send(handler, content);
} else {
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0,
StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}

private static void Send(Socket handler, String data) {
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);

// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}

private static void SendCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket handler = (Socket) ar.AsyncState;

// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);

handler.Shutdown(SocketShutdown.Both);
handler.Close();

} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
 
S

Sebastian [IG&A::]

You probably can but I don't think is safe unless you know the exact
length of the pakets sent to you.
I would use, and as a matter of fact I do use, a loop and bytes why
there's still some.
After that I close the stream.

I don't have an example right here so if you need one tell me and'll
look for it.

Regards.
Seba
 
W

William Stacey [MVP]

You must always *expect you will get 1 or more bytes (or 0 if shutdown by
sender) upto max of Count bytes. That is all you can expect and you need to
design your logic always with that understanding. The sender may be sending
4 bytes (maybe a length) as one Send and then sending the data as the second
Send(). This could be because they wanted to save a buffer copy to join the
two arrays. On the other hand, that could make less efficient network
traffic if it means the first send/ack will always be only 4 bytes. So do
you pay the price in the buffer join(s) or slightly more traffic. Can't
really say as it depends on the app, net speed, etc.

--
William Stacey [MVP]

| Hi,
|
| I have a synchronous socket server which my app uses to read data from
| clients.
|
| To test this I have a simulated client that sends 100 byte packets.
|
| I have set up the socket server so that its buffer is bigger than this.
| I did this expecting the data to be read in one pass.
|
| However what I find is that on the first pass it only reads the first 4
| bytes and then on the second pass of begin.receive, reads the rest of the
| message. Is this usual?
|
| This happens each time I send my packet from the
| The code I have been using is the MSDN example( shown below).
|
| Can anyone tell me if it is possible to read the whole message sent form
the
| client on the first pass rather than it taking 2 or more passes?
|
| Thanks
| Macca
|
|
| using System;
| using System.Net;
| using System.Net.Sockets;
| using System.Text;
| using System.Threading;
|
| // State object for reading client data asynchronously
| public class StateObject {
| // Client socket.
| public Socket workSocket = null;
| // Size of receive buffer.
| public const int BufferSize = 100;
| // Receive buffer.
| public byte[] buffer = new byte[BufferSize];
| // Received data string.
| public StringBuilder sb = new StringBuilder();
| }
|
| public class AsynchronousSocketListener {
| // Thread signal.
| public static ManualResetEvent allDone = new ManualResetEvent(false);
|
| public AsynchronousSocketListener() {
| }
|
| public static void StartListening() {
| // Data buffer for incoming data.
| byte[] bytes = new Byte[1024];
|
| // Establish the local endpoint for the socket.
| // The DNS name of the computer
| // running the listener is "host.contoso.com".
| SN.IPHostEntry ipHostInfo = SN.Dns.GetHostEntry(hostname);
| SN.IPAddress ipAddress = ipHostInfo.AddressList[0];
| SN.IPEndPoint localEndPoint = new SN.IPEndPoint(ipAddress,
7777);
|
| // Create a TCP/IP socket.
| Socket listener = new Socket(AddressFamily.InterNetwork,
| SocketType.Stream, ProtocolType.Tcp );
|
| // Bind the socket to the local endpoint and listen for incoming
| connections.
| try {
| listener.Bind(localEndPoint);
| listener.Listen(100);
|
| while (true) {
| // Set the event to nonsignaled state.
| allDone.Reset();
|
| // Start an asynchronous socket to listen for connections.
| Console.WriteLine("Waiting for a connection...");
| listener.BeginAccept(
| new AsyncCallback(AcceptCallback),
| listener );
|
| // Wait until a connection is made before continuing.
| allDone.WaitOne();
| }
|
| } catch (Exception e) {
| Console.WriteLine(e.ToString());
| }
|
| Console.WriteLine("\nPress ENTER to continue...");
| Console.Read();
|
| }
|
| public static void AcceptCallback(IAsyncResult ar) {
| // Signal the main thread to continue.
| allDone.Set();
|
| // Get the socket that handles the client request.
| Socket listener = (Socket) ar.AsyncState;
| Socket handler = listener.EndAccept(ar);
|
| // Create the state object.
| StateObject state = new StateObject();
| state.workSocket = handler;
| handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
| new AsyncCallback(ReadCallback), state);
| }
|
| public static void ReadCallback(IAsyncResult ar) {
| String content = String.Empty;
|
| // Retrieve the state object and the handler socket
| // from the asynchronous state object.
| StateObject state = (StateObject) ar.AsyncState;
| Socket handler = state.workSocket;
|
| // Read data from the client socket.
| int bytesRead = handler.EndReceive(ar);
|
| if (bytesRead > 0) {
| // There might be more data, so store the data received so
far.
| state.sb.Append(Encoding.ASCII.GetString(
| state.buffer,0,bytesRead));
|
| // Check for end-of-file tag. If it is not there, read
| // more data.
| content = state.sb.ToString();
| if (content.IndexOf("<EOF>") > -1) {
| // All the data has been read from the
| // client. Display it on the console.
| Console.WriteLine("Read {0} bytes from socket. \n Data :
{1}",
| content.Length, content );
| // Echo the data back to the client.
| Send(handler, content);
| } else {
| // Not all data received. Get more.
| handler.BeginReceive(state.buffer, 0,
| StateObject.BufferSize, 0,
| new AsyncCallback(ReadCallback), state);
| }
| }
| }
|
| private static void Send(Socket handler, String data) {
| // Convert the string data to byte data using ASCII encoding.
| byte[] byteData = Encoding.ASCII.GetBytes(data);
|
| // Begin sending the data to the remote device.
| handler.BeginSend(byteData, 0, byteData.Length, 0,
| new AsyncCallback(SendCallback), handler);
| }
|
| private static void SendCallback(IAsyncResult ar) {
| try {
| // Retrieve the socket from the state object.
| Socket handler = (Socket) ar.AsyncState;
|
| // Complete sending the data to the remote device.
| int bytesSent = handler.EndSend(ar);
| Console.WriteLine("Sent {0} bytes to client.", bytesSent);
|
| handler.Shutdown(SocketShutdown.Both);
| handler.Close();
|
| } catch (Exception e) {
| Console.WriteLine(e.ToString());
| }
| }
|
 
G

Guest

Hi william,

At the moment I know the exact size of each packet. It just surprises me
that every time I send a packet the first pass always sends 4 bytes then the
second time it sends the rest.

Would there ever be an occasion when the whole packet would be received on
the first pass?

Also I am looking into the most efficient way of detecting when the full
packet has been received. The Packet does not have and end of packet
indicator. I know I could use a counter to detect how many bytes have been
received and compare against the packet size but is this the most efficient
way of doing it?

Regards
Macca

William Stacey said:
You must always *expect you will get 1 or more bytes (or 0 if shutdown by
sender) upto max of Count bytes. That is all you can expect and you need to
design your logic always with that understanding. The sender may be sending
4 bytes (maybe a length) as one Send and then sending the data as the second
Send(). This could be because they wanted to save a buffer copy to join the
two arrays. On the other hand, that could make less efficient network
traffic if it means the first send/ack will always be only 4 bytes. So do
you pay the price in the buffer join(s) or slightly more traffic. Can't
really say as it depends on the app, net speed, etc.

--
William Stacey [MVP]

| Hi,
|
| I have a synchronous socket server which my app uses to read data from
| clients.
|
| To test this I have a simulated client that sends 100 byte packets.
|
| I have set up the socket server so that its buffer is bigger than this.
| I did this expecting the data to be read in one pass.
|
| However what I find is that on the first pass it only reads the first 4
| bytes and then on the second pass of begin.receive, reads the rest of the
| message. Is this usual?
|
| This happens each time I send my packet from the
| The code I have been using is the MSDN example( shown below).
|
| Can anyone tell me if it is possible to read the whole message sent form
the
| client on the first pass rather than it taking 2 or more passes?
|
| Thanks
| Macca
|
|
| using System;
| using System.Net;
| using System.Net.Sockets;
| using System.Text;
| using System.Threading;
|
| // State object for reading client data asynchronously
| public class StateObject {
| // Client socket.
| public Socket workSocket = null;
| // Size of receive buffer.
| public const int BufferSize = 100;
| // Receive buffer.
| public byte[] buffer = new byte[BufferSize];
| // Received data string.
| public StringBuilder sb = new StringBuilder();
| }
|
| public class AsynchronousSocketListener {
| // Thread signal.
| public static ManualResetEvent allDone = new ManualResetEvent(false);
|
| public AsynchronousSocketListener() {
| }
|
| public static void StartListening() {
| // Data buffer for incoming data.
| byte[] bytes = new Byte[1024];
|
| // Establish the local endpoint for the socket.
| // The DNS name of the computer
| // running the listener is "host.contoso.com".
| SN.IPHostEntry ipHostInfo = SN.Dns.GetHostEntry(hostname);
| SN.IPAddress ipAddress = ipHostInfo.AddressList[0];
| SN.IPEndPoint localEndPoint = new SN.IPEndPoint(ipAddress,
7777);
|
| // Create a TCP/IP socket.
| Socket listener = new Socket(AddressFamily.InterNetwork,
| SocketType.Stream, ProtocolType.Tcp );
|
| // Bind the socket to the local endpoint and listen for incoming
| connections.
| try {
| listener.Bind(localEndPoint);
| listener.Listen(100);
|
| while (true) {
| // Set the event to nonsignaled state.
| allDone.Reset();
|
| // Start an asynchronous socket to listen for connections.
| Console.WriteLine("Waiting for a connection...");
| listener.BeginAccept(
| new AsyncCallback(AcceptCallback),
| listener );
|
| // Wait until a connection is made before continuing.
| allDone.WaitOne();
| }
|
| } catch (Exception e) {
| Console.WriteLine(e.ToString());
| }
|
| Console.WriteLine("\nPress ENTER to continue...");
| Console.Read();
|
| }
|
| public static void AcceptCallback(IAsyncResult ar) {
| // Signal the main thread to continue.
| allDone.Set();
|
| // Get the socket that handles the client request.
| Socket listener = (Socket) ar.AsyncState;
| Socket handler = listener.EndAccept(ar);
|
| // Create the state object.
| StateObject state = new StateObject();
| state.workSocket = handler;
| handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
| new AsyncCallback(ReadCallback), state);
| }
|
| public static void ReadCallback(IAsyncResult ar) {
| String content = String.Empty;
|
| // Retrieve the state object and the handler socket
| // from the asynchronous state object.
| StateObject state = (StateObject) ar.AsyncState;
| Socket handler = state.workSocket;
|
| // Read data from the client socket.
| int bytesRead = handler.EndReceive(ar);
|
| if (bytesRead > 0) {
| // There might be more data, so store the data received so
far.
| state.sb.Append(Encoding.ASCII.GetString(
| state.buffer,0,bytesRead));
|
| // Check for end-of-file tag. If it is not there, read
| // more data.
| content = state.sb.ToString();
| if (content.IndexOf("<EOF>") > -1) {
| // All the data has been read from the
| // client. Display it on the console.
| Console.WriteLine("Read {0} bytes from socket. \n Data :
{1}",
| content.Length, content );
| // Echo the data back to the client.
| Send(handler, content);
| } else {
| // Not all data received. Get more.
| handler.BeginReceive(state.buffer, 0,
| StateObject.BufferSize, 0,
| new AsyncCallback(ReadCallback), state);
| }
| }
| }
|
| private static void Send(Socket handler, String data) {
| // Convert the string data to byte data using ASCII encoding.
| byte[] byteData = Encoding.ASCII.GetBytes(data);
|
| // Begin sending the data to the remote device.
| handler.BeginSend(byteData, 0, byteData.Length, 0,
| new AsyncCallback(SendCallback), handler);
| }
|
| private static void SendCallback(IAsyncResult ar) {
| try {
| // Retrieve the socket from the state object.
| Socket handler = (Socket) ar.AsyncState;
|
| // Complete sending the data to the remote device.
| int bytesSent = handler.EndSend(ar);
| Console.WriteLine("Sent {0} bytes to client.", bytesSent);
|
| handler.Shutdown(SocketShutdown.Both);
| handler.Close();
|
| } catch (Exception e) {
| Console.WriteLine(e.ToString());
| }
| }
|
 
W

William Stacey [MVP]

| At the moment I know the exact size of each packet. It just surprises me
| that every time I send a packet the first pass always sends 4 bytes then
the
| second time it sends the rest.

How is the send side sending the bytes? Is it using two sends or one?

| Also I am looking into the most efficient way of detecting when the full
| packet has been received. The Packet does not have and end of packet
| indicator. I know I could use a counter to detect how many bytes have been
| received and compare against the packet size but is this the most
efficient
| way of doing it?

Yes. Read till X bytes received. That is the best way to do it and is very
common and well known pattern for network streams.
Here is a general pattern you can use on receives to receive byte[numBytes]
or Null if socket closed by client.

private byte[] FillBuffer(int numBytes)
{
int totRead = 0;
int read = 0;

if (numBytes == 1)
{
read = this.innerStream.ReadByte();
if (read == -1)
return null;
return new byte[] { (byte)read };
}
else
{
byte[] buff = new byte[numBytes];
do
{
read = this.innerStream.Read(buff, totRead, numBytes -
totRead);
if (read == 0)
return null;
totRead += read;
}
while (totRead < numBytes);
return buff;
}
}
 
G

Guest

Hi William,

The send side is only using one send to send the data, however it is doing
serially to a third party device that then sends the data on to the "server"
pc over TCP sockets. I'm not sure wehter it is something to do with the
socket server or perhaps something to do with the third party device that
converts serial data to tcp socket data.

Any thoughts?

Thanks
Macca
 
W

William Stacey [MVP]

No ideas. I would only say it does not really matter as long as you know
the len and can get len bytes. Even if the sender does do one send, you can
not (and should not) ever expect you will get the whole message in one read.
It is just the way it works with sockets.

--
William Stacey [MVP]

| Hi William,
|
| The send side is only using one send to send the data, however it is doing
| serially to a third party device that then sends the data on to the
"server"
| pc over TCP sockets. I'm not sure wehter it is something to do with the
| socket server or perhaps something to do with the third party device that
| converts serial data to tcp socket data.
|
| Any thoughts?
|
| Thanks
| Macca
|
| "William Stacey [MVP]" wrote:
|
| > | At the moment I know the exact size of each packet. It just surprises
me
| > | that every time I send a packet the first pass always sends 4 bytes
then
| > the
| > | second time it sends the rest.
| >
| > How is the send side sending the bytes? Is it using two sends or one?
| >
| > | Also I am looking into the most efficient way of detecting when the
full
| > | packet has been received. The Packet does not have and end of packet
| > | indicator. I know I could use a counter to detect how many bytes have
been
| > | received and compare against the packet size but is this the most
| > efficient
| > | way of doing it?
| >
| > Yes. Read till X bytes received. That is the best way to do it and is
very
| > common and well known pattern for network streams.
| > Here is a general pattern you can use on receives to receive
byte[numBytes]
| > or Null if socket closed by client.
| >
| > private byte[] FillBuffer(int numBytes)
| > {
| > int totRead = 0;
| > int read = 0;
| >
| > if (numBytes == 1)
| > {
| > read = this.innerStream.ReadByte();
| > if (read == -1)
| > return null;
| > return new byte[] { (byte)read };
| > }
| > else
| > {
| > byte[] buff = new byte[numBytes];
| > do
| > {
| > read = this.innerStream.Read(buff, totRead,
numBytes -
| > totRead);
| > if (read == 0)
| > return null;
| > totRead += read;
| > }
| > while (totRead < numBytes);
| > return buff;
| > }
| > }
| >
| >
| > --
| > William Stacey [MVP]
| >
| >
| >
| >
 
G

Guest

William,

Is it possible for me to incorporate this FillBuffer() method into an
ansynchronous socket methodology.

I have a read callback method that is called when any data is detected at
the connected socket as shown below in code I got form MSDN :-

Regards
Macca

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

// State object for reading client data asynchronously
public class StateObject {
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}

public class AsynchronousSocketListener {
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);

public AsynchronousSocketListener() {
}

public static void StartListening() {
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];

// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);

// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );

// Bind the socket to the local endpoint and listen for incoming
connections.
try {
listener.Bind(localEndPoint);
listener.Listen(100);

while (true) {
// Set the event to nonsignaled state.
allDone.Reset();

// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener );

// Wait until a connection is made before continuing.
allDone.WaitOne();
}

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

Console.WriteLine("\nPress ENTER to continue...");
Console.Read();

}

public static void AcceptCallback(IAsyncResult ar) {
// Signal the main thread to continue.
allDone.Set();

// Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar);

// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}

public static void ReadCallback(IAsyncResult ar) {
String content = String.Empty;

// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject) ar.AsyncState;
Socket handler = state.workSocket;

// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);

if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer,0,bytesRead));

// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1) {
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content );
// Echo the data back to the client.
Send(handler, content);
} else {
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0,
StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}

private static void Send(Socket handler, String data) {
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);

// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}

private static void SendCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket handler = (Socket) ar.AsyncState;

// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);

handler.Shutdown(SocketShutdown.Both);
handler.Close();

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


public static int Main(String[] args) {
StartListening();
return 0;
}
}





William Stacey said:
| At the moment I know the exact size of each packet. It just surprises me
| that every time I send a packet the first pass always sends 4 bytes then
the
| second time it sends the rest.

How is the send side sending the bytes? Is it using two sends or one?

| Also I am looking into the most efficient way of detecting when the full
| packet has been received. The Packet does not have and end of packet
| indicator. I know I could use a counter to detect how many bytes have been
| received and compare against the packet size but is this the most
efficient
| way of doing it?

Yes. Read till X bytes received. That is the best way to do it and is very
common and well known pattern for network streams.
Here is a general pattern you can use on receives to receive byte[numBytes]
or Null if socket closed by client.

private byte[] FillBuffer(int numBytes)
{
int totRead = 0;
int read = 0;

if (numBytes == 1)
{
read = this.innerStream.ReadByte();
if (read == -1)
return null;
return new byte[] { (byte)read };
}
else
{
byte[] buff = new byte[numBytes];
do
{
read = this.innerStream.Read(buff, totRead, numBytes -
totRead);
if (read == 0)
return null;
totRead += read;
}
while (totRead < numBytes);
return buff;
}
}
 

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