いくつかの発言から、あなたが何をしているのかよくわかりません。あなたは使用していると書いていますが、またはSocketAsyncEventArgs
のような奇妙な API を処理しようとしています。ソケットの種類が TCP の場合、パケットは常に正しい順序で処理されるため、何か間違ったことをしている可能性があります。それらはわずか 1 バイト サイズのチャンクに断片化されることもありますが、順序は正しくなります。それがTCPのすべてです。.Count
.Available
コードを提供しておらず、ステートメントに基づいているため、開始するにはSSCEを提供するのが最善だと思います。
サンプルは C# ですが、VB.net に適用する必要があります。コード内のコメントをチェックして、実際に受信したデータをどこから適切に取得するかを確認してください。実装は、受信したデータをコンソールに書き込み、クライアントに送り返します。Echo サーバーはすばらしいサンプルを作成します。
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace SaeaSample
{
public class Program
{
static void Main()
{
var server = new Server(new IPEndPoint(IPAddress.Any, 12345));
// ugly sample clients
Parallel.For(0, 4, i =>
{
using (var client = new TcpClient("localhost", 12345))
using (var stream = client.GetStream())
using (var writer = new BinaryWriter(stream))
using (var reader = new BinaryReader(stream))
{
var text = "Hello Async-Server!";
var message = Encoding.UTF8.GetBytes(text);
Console.WriteLine("s: {0}: {1}", i, text);
writer.Write(message);
var roundtrip = reader.ReadBytes(message.Length);
Console.WriteLine("r: {0}: {1}", i, Encoding.UTF8.GetString(roundtrip));
}
});
Console.ReadLine();
}
}
public class Server
{
private const int readBufferSize = 8192;
private const int sendBufferSize = readBufferSize;
// just have a fixed number of clients instead of
// pooling for the sake of being an example
private const int maxClients = 4;
private const int maxQueue = 10;
private readonly byte[] buffer = new byte[maxClients * (readBufferSize + sendBufferSize)];
private readonly Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public Server(IPEndPoint localEndPoint)
{
socket.Bind(localEndPoint);
socket.Listen(maxQueue);
for (int i = 0; i < maxClients; i++)
{
var client = new UserToken(i);
client.RecvArgs.Completed += completed;
client.SendArgs.Completed += completed;
Console.WriteLine("accepting on client slot {0}", client.Slot);
if (!socket.AcceptAsync(client.RecvArgs))
{
completed(this, client.RecvArgs);
}
}
}
private void completed(object sender, SocketAsyncEventArgs e)
{
var client = (UserToken)e.UserToken;
// socket operation had success
if (e.SocketError == SocketError.Success)
{
// new client connected
if (e.LastOperation == SocketAsyncOperation.Accept)
{
onAccept(client);
}
// either send or received worked
else if (e.BytesTransferred > 0)
{
if (e.LastOperation == SocketAsyncOperation.Receive)
{
onReceived(client);
}
else if (e.LastOperation == SocketAsyncOperation.Send)
{
onSend(client);
}
// should never happen, handle gracefully
else
{
onOther(client);
}
}
// don't handle anything else
else
{
onOther(client);
}
}
// socket error occured
else
{
onOther(client);
}
}
private void onAccept(UserToken client)
{
Console.WriteLine("client slot {0} connected client from {1}", client.Slot, client.RecvArgs.AcceptSocket.RemoteEndPoint);
// once accepted, start receiving
client.RecvArgs.SetBuffer(buffer, client.Slot * (readBufferSize + sendBufferSize), readBufferSize);
if (!client.RecvArgs.AcceptSocket.ReceiveAsync(client.RecvArgs))
{
completed(this, client.RecvArgs);
}
}
private void onReceived(UserToken client)
{
// echo whatever we got
var builder = new StringBuilder();
// here is the important part
for (int i = 0; i < client.RecvArgs.BytesTransferred; i++)
{
// offset the buffer and echo in hex
builder.Append(client.RecvArgs.Buffer[client.Slot * (readBufferSize + sendBufferSize) + i].ToString("x2"));
}
Console.WriteLine("received {0} bytes from client slot {1}: {2}", client.RecvArgs.BytesTransferred, client.Slot, builder.ToString());
// send data back ... this is an echo server after all
client.SendArgs.SetBuffer(client.RecvArgs.Buffer, client.Slot * (readBufferSize + sendBufferSize) + readBufferSize, client.RecvArgs.BytesTransferred);
Buffer.BlockCopy(client.RecvArgs.Buffer, client.RecvArgs.Offset, client.SendArgs.Buffer, client.SendArgs.Offset, client.RecvArgs.BytesTransferred);
if (!client.RecvArgs.AcceptSocket.SendAsync(client.SendArgs))
{
completed(this, client.SendArgs);
}
}
private void onSend(UserToken client)
{
Console.WriteLine("sent {0} bytes back to client slot {1}", client.SendArgs.BytesTransferred, client.Slot);
// start receiving again
if (!client.RecvArgs.AcceptSocket.ReceiveAsync(client.RecvArgs))
{
completed(this, client.RecvArgs);
}
}
private void onOther(UserToken client)
{
Console.WriteLine("disconnecting client slot {0}", client.Slot);
// just close the connection and accept again
client.RecvArgs.SetBuffer(null, 0, 0);
if (client.RecvArgs.AcceptSocket != null) {
client.RecvArgs.AcceptSocket.Dispose();
client.RecvArgs.AcceptSocket = null;
}
Console.WriteLine("accepting on client slot {0}", client.Slot);
if (!socket.AcceptAsync(client.RecvArgs))
{
completed(this, client.RecvArgs);
}
}
}
public class UserToken
{
public readonly int Slot;
public readonly SocketAsyncEventArgs RecvArgs = new SocketAsyncEventArgs();
public readonly SocketAsyncEventArgs SendArgs = new SocketAsyncEventArgs();
public UserToken(int slot)
{
Slot = slot;
RecvArgs.UserToken = this;
SendArgs.UserToken = this;
}
}
}
また、このコードは非同期であるため、コンソール出力が常に正しい順序である場合とそうでない場合があることに注意してください。読み取りおよび書き込みバッファー サイズの定数を 8192 から 1 まで減らすことができます。パケットはバイト単位で両方向に送信されますが、確実に順番通りに送信されます。
より詳細な説明については、 MSDNが常に出発点として適しています。