[新人求解]关于socket异步调用

xz9577 2017-11-27 09:50:57
private void AsyncConnect(IPAddress host, uint port)
{
try
{
GameUtils.Logger.Net.Log("AsyncConnect:"+host+" port:"+port);
lock(lockObj)
{
if (clientSocket == null)
{
clientSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
clientSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.Linger,
new LingerOption(false, 0));
clientSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveBuffer,
NetOptions.SOCKET_MAX_RECV_SIZE);
clientSocket.ReceiveTimeout = NetOptions.Timeout;
clientSocket.SendTimeout = NetOptions.Timeout;
}

clientSocket.BeginConnect(
new IPEndPoint(host, (int)port),
new AsyncCallback(connectCallback),
clientSocket
);
}
}
catch (Exception exception)
{
GameUtils.Logger.Net.LogException(exception);
}
}

---------------------------------------------------------------------
private void connectCallback(IAsyncResult asyncConnect)
{
Socket socket = (Socket)asyncConnect.AsyncState;
if (socket == null)
{
return;
}

try
{
socket.EndConnect(asyncConnect);
if (asyncConnect.IsCompleted && socket.Connected)
{
PushInternalMsg(Packet.enInternalMsgType.Connected);
BeginReceive(socket);
}
}
catch (SocketException e)
{
GameUtils.Logger.Net.Log(e.Message);
OnSocketDisconnect();
}
catch (Exception e)
{
GameUtils.Logger.Net.Log(e.Message);
}
}

-----------------------------------------------

private void BeginReceive(Socket socket)
{
try
{
if (!socket.Connected)
{
return;
}

socket.BeginReceive(
_byteRecvBuffer,
_recvBufferSize,
NetOptions.SOCKET_MAX_RECV_SIZE - _recvBufferSize,
SocketFlags.None,
//new AsyncCallback(receiveCallback),
receiveCallback,
clientSocket
);
}
catch (Exception e)
{
GameUtils.Logger.Net.Log(e.Message);
OnSocketDisconnect();
}
}


---------------------------------
private void receiveCallback(IAsyncResult ar)
{
try
{
var socket = (Socket)ar.AsyncState;
if (!ar.IsCompleted || socket == null || socket.Connected == false)
{
return;
}

int length = socket.EndReceive(ar); //在IOS上面这行报错 operation on non-blocking socket would block
if (length == 0)
{
OnSocketDisconnect();
return;
}

_recvBufferSize = _recvBufferSize + length;
//
_lastRecvTime = (uint)System.Environment.TickCount;
//Split
while (true)
{


Packet packet = _packetBuilder.FromBytes(_byteRecvBuffer, _recvBufferSize,true);

if (packet == null)
{
BeginReceive(socket);
return;
}
else
{
_recvBufferSize = _recvBufferSize - (int)packet.Size;

Buffer.BlockCopy(_byteRecvBuffer, (int)packet.Size, _byteRecvBuffer, 0, _recvBufferSize);


_recvPacketCount++;

lock (((ICollection)_packetlist).SyncRoot)
{
_packetlist.Add(packet);
}
}
}
}
catch (SocketException e)
{
GameUtils.Logger.Net.Log(e.Message);
OnSocketDisconnect();
}
catch (Exception e)
{
GameUtils.Logger.Net.Log(e.Message);
}
}
...全文
309 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
wisezZz 2018-03-21
  • 打赏
  • 举报
回复
不知道楼主还在不在,我最近也在看这套通信框架,测试后发现在IOS有问题是因为这句 :clientSocket.ReceiveTimeout = NetOptions.Timeout;导致的,但不知道为什么,请问楼主有没有继续研究这个问题?
xian_wwq 2017-11-29
  • 打赏
  • 举报
回复
引用 10 楼 xz9577 的回复:
[quote=引用 9 楼 guanyinsishengzi 的回复:] [quote=引用 8 楼 xz9577 的回复:] [quote=引用 6 楼 xz9577 的回复:] [quote=引用 4 楼 guanyinsishengzi 的回复:] [quote=引用 2 楼 xz9577 的回复:] [quote=引用 1 楼 guanyinsishengzi 的回复:] 改用IOCP
那这个方法行不通是吗?这个可以不可以挽救一下的呢?[/quote] socket.BeginReceive( _byteRecvBuffer, _recvBufferSize, NetOptions.SOCKET_MAX_RECV_SIZE - _recvBufferSize, SocketFlags.None, //new AsyncCallback(receiveCallback), receiveCallback, clientSocke ); clientSocke改为socket [/quote] 大佬还是不行~心态爆炸T T[/quote] 错应该就在这 你再认真试一下[/quote] 我把 if (clientSocket == null) { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); -----------> 创建一个tcp socket clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(false, 0)); ----------------> 设置该socket的Linger属性 clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, NetOptions.SOCKET_MAX_RECV_SIZE);-------------------->设置该socket 的接收Buffer大小 clientSocket.ReceiveTimeout = NetOptions.Timeout; --------->设置socket的接收超时 clientSocket.SendTimeout = NetOptions.Timeout;-------------->设置socket的发送超时 } 这些给注释掉了,改为只用这一段代码 clientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); 就可以了,想问一下是为什么呢? [/quote] 如果不设置相关属性参数,使用默认肯定也可以 SocketOptionName说明详见 https://technet.microsoft.com/zh-cn/library/system.net.sockets.socketoptionname(en-us,VS.85).aspx
xz9577 2017-11-29
  • 打赏
  • 举报
回复
引用 9 楼 guanyinsishengzi 的回复:
[quote=引用 8 楼 xz9577 的回复:] [quote=引用 6 楼 xz9577 的回复:] [quote=引用 4 楼 guanyinsishengzi 的回复:] [quote=引用 2 楼 xz9577 的回复:] [quote=引用 1 楼 guanyinsishengzi 的回复:] 改用IOCP
那这个方法行不通是吗?这个可以不可以挽救一下的呢?[/quote] socket.BeginReceive( _byteRecvBuffer, _recvBufferSize, NetOptions.SOCKET_MAX_RECV_SIZE - _recvBufferSize, SocketFlags.None, //new AsyncCallback(receiveCallback), receiveCallback, clientSocke ); clientSocke改为socket [/quote] 大佬还是不行~心态爆炸T T[/quote] 错应该就在这 你再认真试一下[/quote] 我把 if (clientSocket == null) { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(false, 0)); clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, NetOptions.SOCKET_MAX_RECV_SIZE); clientSocket.ReceiveTimeout = NetOptions.Timeout; clientSocket.SendTimeout = NetOptions.Timeout; } 这些给注释掉了,改为只用这一段代码 clientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); 就可以了,想问一下是为什么呢? 看官方文档说 : "如果你想要将默认远程主机为广播地址,必须先调用 SetSocketOption 并设置为广播 true。 如果不能 BeginConnect 将引发 SocketException。" 这个是什么意思呢大佬?
guanyinsishengzi 2017-11-27
  • 打赏
  • 举报
回复
引用 8 楼 xz9577 的回复:
[quote=引用 6 楼 xz9577 的回复:] [quote=引用 4 楼 guanyinsishengzi 的回复:] [quote=引用 2 楼 xz9577 的回复:] [quote=引用 1 楼 guanyinsishengzi 的回复:] 改用IOCP
那这个方法行不通是吗?这个可以不可以挽救一下的呢?[/quote] socket.BeginReceive( _byteRecvBuffer, _recvBufferSize, NetOptions.SOCKET_MAX_RECV_SIZE - _recvBufferSize, SocketFlags.None, //new AsyncCallback(receiveCallback), receiveCallback, clientSocke ); clientSocke改为socket [/quote] 大佬还是不行~心态爆炸T T[/quote] 错应该就在这 你再认真试一下
xz9577 2017-11-27
  • 打赏
  • 举报
回复
引用 6 楼 xz9577 的回复:
[quote=引用 4 楼 guanyinsishengzi 的回复:] [quote=引用 2 楼 xz9577 的回复:] [quote=引用 1 楼 guanyinsishengzi 的回复:] 改用IOCP
那这个方法行不通是吗?这个可以不可以挽救一下的呢?[/quote] socket.BeginReceive( _byteRecvBuffer, _recvBufferSize, NetOptions.SOCKET_MAX_RECV_SIZE - _recvBufferSize, SocketFlags.None, //new AsyncCallback(receiveCallback), receiveCallback, clientSocke ); clientSocke改为socket [/quote] 大佬还是不行~心态爆炸T T
xian_wwq 2017-11-27
  • 打赏
  • 举报
回复
引用 5 楼 xz9577 的回复:
[quote=引用 3 楼 xian_wwq 的回复:] 使用SocketAsyncEventArgs底层就是iocp 也是异步调用, 性能要好很多
老实说,我不怎么懂Socket这个东西,其实现在只知道那里报错了,SocketAsyncEventArgs这个我刚刚百度了一下更加看不懂...[/quote] 都是异步调用, 使用模式基本类似,学习难度也差不多 所以推荐lz直接到位。 当然,如果现在的应用场景对性能不是很苛刻, 异步调用肯定也能用的
xz9577 2017-11-27
  • 打赏
  • 举报
回复
引用 4 楼 guanyinsishengzi 的回复:
[quote=引用 2 楼 xz9577 的回复:] [quote=引用 1 楼 guanyinsishengzi 的回复:] 改用IOCP
那这个方法行不通是吗?这个可以不可以挽救一下的呢?[/quote] socket.BeginReceive( _byteRecvBuffer, _recvBufferSize, NetOptions.SOCKET_MAX_RECV_SIZE - _recvBufferSize, SocketFlags.None, //new AsyncCallback(receiveCallback), receiveCallback, clientSocke ); clientSocke改为socket [/quote] 感谢大佬 我试一下
xz9577 2017-11-27
  • 打赏
  • 举报
回复
引用 3 楼 xian_wwq 的回复:
使用SocketAsyncEventArgs底层就是iocp 也是异步调用, 性能要好很多
老实说,我不怎么懂Socket这个东西,其实现在只知道那里报错了,SocketAsyncEventArgs这个我刚刚百度了一下更加看不懂...
guanyinsishengzi 2017-11-27
  • 打赏
  • 举报
回复
引用 2 楼 xz9577 的回复:
[quote=引用 1 楼 guanyinsishengzi 的回复:] 改用IOCP
那这个方法行不通是吗?这个可以不可以挽救一下的呢?[/quote] socket.BeginReceive( _byteRecvBuffer, _recvBufferSize, NetOptions.SOCKET_MAX_RECV_SIZE - _recvBufferSize, SocketFlags.None, //new AsyncCallback(receiveCallback), receiveCallback, clientSocke ); clientSocke改为socket
xian_wwq 2017-11-27
  • 打赏
  • 举报
回复
使用SocketAsyncEventArgs底层就是iocp 也是异步调用, 性能要好很多
xz9577 2017-11-27
  • 打赏
  • 举报
回复
引用 1 楼 guanyinsishengzi 的回复:
改用IOCP
那这个方法行不通是吗?这个可以不可以挽救一下的呢?
guanyinsishengzi 2017-11-27
  • 打赏
  • 举报
回复
改用IOCP

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧