Теперь я пишу крошечный фреймворк на основе SocketAsyncEventArgs, этот класс создан на основе IOCP, который намного эффективнее, чем режим APM. , но здесь у меня возникли проблемы при запуске теста. здесь код сервера:Почему, похоже, мое TCP-соединение потеряет пакеты на стороне сервера?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Windows.Forms;
namespace SocketServer
{
public class Server
{
Socket serverSocket;
SocketAsyncEventArgs socketAsyncEventArgs;
SocketAsyncEventArgsPool readWritePool;
HandleMessage handleMessage;
BufferManager buffeManager;
const int PrefixSize = 11;
public void Init(int port,int connections,int receiveBufferSize)
{
buffeManager = new BufferManager(receiveBufferSize * connections * 2, receiveBufferSize);
buffeManager.InitBuffer();
readWritePool = new SocketAsyncEventArgsPool(connections);
SocketAsyncEventArgs socketAsyncEventArgsPooling;
for (int i = 0; i < connections; i++)
{
socketAsyncEventArgsPooling = new SocketAsyncEventArgs();
socketAsyncEventArgsPooling.Completed += readEventArgsIO_Completed;
buffeManager.SetBuffer(socketAsyncEventArgsPooling);
readWritePool.Push(socketAsyncEventArgsPooling);
}
handleMessage = new HandleMessage();
IPAddress[] addressList = Dns.GetHostEntry(Environment.MachineName).AddressList;
IPEndPoint localEndPoint = new IPEndPoint(addressList[addressList.Length - 1], port);
this.serverSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
{
this.serverSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
this.serverSocket.Bind(new IPEndPoint(IPAddress.IPv6Any, localEndPoint.Port));
}
else
{
this.serverSocket.Bind(localEndPoint);
}
this.serverSocket.Listen(100);
StartAccept(null);
}
private void StartAccept(SocketAsyncEventArgs acceptSocketAsyncEventArgs)
{
if (acceptSocketAsyncEventArgs == null)
{
acceptSocketAsyncEventArgs = new SocketAsyncEventArgs();
acceptSocketAsyncEventArgs.Completed += socketAsyncEventArgs_Completed;
}
else
{
acceptSocketAsyncEventArgs.AcceptSocket = null;
}
Boolean willRaiseEvent = this.serverSocket.AcceptAsync(acceptSocketAsyncEventArgs);
if (!willRaiseEvent)
{
this.ProcessAccept(acceptSocketAsyncEventArgs);
}
}
private void socketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
{
ProcessAccept(e);
}
private void readEventArgsIO_Completed(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
this.ProcessReceive(e);
break;
case SocketAsyncOperation.Send:
//this.ProcessSend(e);
break;
default:
throw new ArgumentException("The last operation completed on the socket was not a receive or send");
}
}
private void ProcessAccept(SocketAsyncEventArgs e)
{
SocketAsyncEventArgs readEventArgs = this.readWritePool.Pop();
//SocketAsyncEventArgs readEventArgs = new SocketAsyncEventArgs();
readEventArgs.UserToken = e.AcceptSocket;
Console.WriteLine("---------------------------------------------------");
Console.WriteLine("Client Connected {0}",e.AcceptSocket.RemoteEndPoint);
Boolean willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs);
if (!willRaiseEvent)
{
this.ProcessReceive(readEventArgs);
}
this.StartAccept(e);
}
private void ProcessReceive(SocketAsyncEventArgs e)
{
if (e.BytesTransferred > 0)
{
if (e.SocketError == SocketError.Success)
{
Console.WriteLine("receiving data, {0} bytes", e.BytesTransferred);
Socket socket = e.UserToken as Socket;
int bytesTransferred = e.BytesTransferred;
string received = Encoding.ASCII.GetString(e.Buffer, e.Offset, bytesTransferred);
Console.WriteLine("Received:{0}", received);
string[] msgArray = handleMessage.GetActualString(received);
foreach (var msg in msgArray)
{
Console.WriteLine("After Split:{0}", msg);
}
// Array.Clear(e.Buffer, e.Offset, bytesTransferred);
Boolean willRaiseEvent = socket.SendAsync(e);
if (!willRaiseEvent)
{
this.ProcessSend(e);
}
readWritePool.Push(e);
}
}
}
private void ProcessSend(SocketAsyncEventArgs e)
{
}
}
}
вот мой код клиента:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace SocketClient
{
class Program
{
static void Main(string[] args)
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse("192.168.2.129"), 1234);
SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();
connectArgs.RemoteEndPoint = ipEndPoint;
connectArgs.Completed += OnConnected;
socket.ConnectAsync(connectArgs);
socket.SendBufferSize = Int16.MaxValue;
//NetworkStream streamToServer = new NetworkStream(socket);
string text = "[length=12]Hello server";
byte[] sendBuffer = Encoding.ASCII.GetBytes(text);
for (int i = 0; i < 5; i++)
{
SocketAsyncEventArgs sendArgs = new SocketAsyncEventArgs();
sendArgs.UserToken = socket;
sendArgs.SetBuffer(sendBuffer,0,sendBuffer.Length);
sendArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);
socket.SendAsync(sendArgs);
}
Console.ReadLine();
}
private static void OnSend(object sender, SocketAsyncEventArgs e)
{
Console.WriteLine("SendOk: {0}", e.UserToken.ToString());
}
private static void OnConnected(object sender, SocketAsyncEventArgs e)
{
Console.WriteLine("Conectioned");
}
}
}
Но когда я начинаю несколько клиентов, я обнаружил, что иногда сервер может правильно получать сообщения; но иногда сервер может получать только первое сообщение, кажущиеся сообщения кажутся «потерянными», каждый может советовать? спасибо.
Я слышал от кого-то, что я должен реализовать свой собственный протокол для передачи данных, но кто-нибудь может сказать мне, как определить? ТНХ
ниже является захват экрана отростка стороне сервера:
Определите «У меня возникли проблемы». – EJP