Reputation: 648
I am new in the Socket Programming and I just want to ask something.
I was trying to create Simple Receiver and Sender packet between the Client and Server (well I am using same computer), but I having a problem...
The sending function is working properly, but I don't know how to receive the packet that was sent with exactly same size of packet.
For example, I send 5 bytes to the server from the client, I just want to server to receive only 5 bytes too, no more and no less and I want to do this with Socket, also i already include the size of packet with short (int16 2 bytes) format. Here my send packet code:
public static void Send(Socket socket, byte[] buffer, int timeout)
{
int startTickCount = Environment.TickCount;
int sent = 0;
int offset = 0;
int size = buffer.Length;
// Add size of packet in the begin of data packet with short (int16) format
List<byte> tmpdata = new List<byte>();
tmpdata.AddRange(BitConverter.GetBytes((short)(buffer.Length + 2)));
tmpdata.AddRange(buffer);
buffer = tmpdata.ToArray();
do
{
if (Environment.TickCount > startTickCount + timeout)
throw new Exception("Sending packet was timeout.");
try
{
sent += socket.Send(buffer, offset + sent, size - sent, SocketFlags.None);
}
catch (SocketException ex)
{
if (ex.SocketErrorCode == SocketError.WouldBlock ||
ex.SocketErrorCode == SocketError.IOPending ||
ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
{
Thread.Sleep(30);
}
else
throw ex;
}
} while (sent < size);
}
Can someone help me?
Thanks Damien for the fix And I was found the solution, but I am afraid this will consume memory usage since it looping each byte, here the code:
public static byte[] Receive(Socket socket)
{
System.Net.Sockets.NetworkStream ns = new NetworkStream(socket);
int b = (byte)1;
List<byte> databuf = new List<byte>();
while ((b = ns.ReadByte()) != -1)
databuf.Add((byte)b);
return databuf.ToArray();
}
There are any better solution without NetworkStream or maybe better performance? Thanks
Upvotes: 0
Views: 2183
Reputation: 486
There are any better solution without NetworkStream or maybe better performance?
NetworkStream acts as a higher level wrapper for Socket, so you could do the same thing using it directly:
var targetStream = new MemoryStream();
var buffer = new byte[receiveBufferSize];
int bytesReceived = 0;
while ((bytesReceived = socket.Receive(buffer)) > 0)
{
targetStream.Write(buffer, 0, bytesReceived);
}
Also there are SendAsync
and ReceiveAsync
methods in Socket
that work well when you need to perform multiple concurrent operations. But they are more complicated:
var receive = new SocketAsyncEventArgs();
var receiveBuffer = new byte[receiveBufferSize];
receive.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
receive.Completed += HandleReceived;
if (!socket.ReceiveAsync(receive))
{
HandleReceived(this, receive);
}
Upvotes: 1
Reputation: 239824
You've not shown your receiving code, but one bug can be easily fixed:
// Add size of packet in the begin of data packet with short (int16) format
List<byte> tmpdata = new List<byte>();
tmpdata.AddRange(BitConverter.GetBytes((short)(buffer.Length + 2)));
tmpdata.AddRange(buffer);
buffer = tmpdata.ToArray();
int size = buffer.Length; //Moved from higher up, now that buffer is a different size
At the receiving side, you should have similar code - loop until you've read 2 bytes, use that to create a short
that is the total size to receive, subtract 2 (honestly, I'd just avoid adding 2 in the code above and have the size sent as the size ignoring the actual bytes used to encode the size), and then loop again until you've read the whole message.
Upvotes: 3