Asynchronous Client Socket和SocketAsyncEventArgs的使用问题

penfe 2011-06-17 10:33:00
小弟正在学习MSDN的例子程序AsyncSocketServer,仿写了个客户端程序,但遇到两个疑惑,请大侠解惑,多谢先:

【疑惑1】当和服务器端的连接建立以后(进入函数ProcessConnect),为什么在这里调用ReceiveAsync就会遭遇NullReferenceException,而调用SendAsync就没问题?
【疑惑2】当调用了函数ReceiveAsync以后且没有数据被接收(处于等待接收状态),这是如果再执行SendAsync会遇到InvalidOperation异常。

代码如下

class Client
{
public bool Connet(string ip, string port)
{
try
{
m_bAvailable = false;
m_dataBuffer = new byte[512];

IPAddress destinationAddr = null; // IP Address of server to connect to
int destinationPort = 0; // Port number of server
destinationAddr = IPAddress.Parse(ip);
destinationPort = int.Parse(port);

m_receiveEventArgs = new SocketAsyncEventArgs();
m_sendEventArgs = new SocketAsyncEventArgs();

// Create a socket and connect to the server
Socket sock = new Socket(destinationAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
m_receiveEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(SocketEventArg_Completed);
m_receiveEventArgs.RemoteEndPoint = new IPEndPoint(destinationAddr, destinationPort);
m_receiveEventArgs.UserToken = sock;

m_sendEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(SocketEventArg_Completed);
m_sendEventArgs.RemoteEndPoint = new IPEndPoint(destinationAddr, destinationPort);
m_sendEventArgs.UserToken = sock;

sock.ConnectAsync(m_receiveEventArgs);

}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return false;
}

return true;
}

public bool Receive()
{
try
{
//Read data sent from the server

Socket sock = m_receiveEventArgs.UserToken as Socket;
Console.WriteLine("calling ReceiveAsync");
bool willRaiseEvent = sock.ReceiveAsync(m_receiveEventArgs);
if (!willRaiseEvent)
{
ProcessReceive(m_receiveEventArgs);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());

return false;
}

return true;
}

public bool IsConnect
{
get
{
return m_bAvailable;
}

}

public bool SendToServer(byte[] buffer)
{
// Send 'Hello World' to the server
//byte[] buffer = Encoding.UTF8.GetBytes("Hello World");
//m_sendEventArgs
Console.WriteLine("Send to server: {0}", Encoding.UTF8.GetString(buffer));

m_receiveEventArgs.SetBuffer(buffer, 0, buffer.Length);
Socket sock = m_receiveEventArgs.UserToken as Socket;

//【疑惑】当执行过ReceiveAsync以后且没有数据被接收(处于等待接收状态)
// 如果执行SendAsync会遇到InvalidOperation异常
bool willRaiseEvent = sock.SendAsync(m_receiveEventArgs);
if (!willRaiseEvent)
{
ProcessSend(m_receiveEventArgs);
}

return true;
}

//心跳检测
public void Ping()
{
// Send 'Hello World' to the server
byte[] buffer = Encoding.UTF8.GetBytes("Hello World");

SendToServer(buffer);
}

protected void ReceiveFromServer(byte[] buffer)
{
}

/// <summary>
/// A single callback is used for all socket operations. This method forwards execution on to the correct handler
/// based on the type of completed operation
/// </summary>
private void SocketEventArg_Completed(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Connect:
ProcessConnect(e);
break;
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
case SocketAsyncOperation.Send:
ProcessSend(e);
break;
default:
throw new Exception("Invalid operation completed");
}
}

/// <summary>
/// Called when a ConnectAsync operation completes
/// </summary>
private void ProcessConnect(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
//m_bAvailable = true;

Console.WriteLine("Successfully connected to the server");

// 【疑惑】为什么在这里ReceiveAsync就会遭遇NullReferenceException,而SendAsync就没问题?
//Receive();// first Receive

Ping();

}
else
{
throw new SocketException((int)e.SocketError);
}
}

/// <summary>
/// Called when a ReceiveAsync operation completes
/// </summary>
private void ProcessReceive(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
Console.WriteLine("Received from server: {0}", Encoding.UTF8.GetString(e.Buffer, 0, e.BytesTransferred));

//粘包等处理逻辑
// TODO:

Receive();// for the next coming data
}
else
{
throw new SocketException((int)e.SocketError);
}
}


/// <summary>
/// Called when a SendAsync operation completes
/// </summary>
private void ProcessSend(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
if (!m_bAvailable)
{
Receive();//第一次发送数据成功后可以开始准备接受数据。
}

m_bAvailable = true;
}
else
{
m_bAvailable = false;

// Disconnect from the server
Socket sock = e.UserToken as Socket;
sock.Shutdown(SocketShutdown.Send);
sock.Close();
//clientDone.Set();
}
}

private SocketAsyncEventArgs m_receiveEventArgs;
private SocketAsyncEventArgs m_sendEventArgs;
private bool m_bAvailable;
private byte[] m_dataBuffer;
}
...全文
203 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
penfe 2011-06-22
  • 打赏
  • 举报
回复
up and up
penfe 2011-06-20
  • 打赏
  • 举报
回复
请问你说的实例化是指什么?有过Send操作?还是有什么方法或属性被设置过?
penfe 2011-06-20
  • 打赏
  • 举报
回复
up and up
jshzp 2011-06-18
  • 打赏
  • 举报
回复
在实例化之前,不能ReceiveAsync操作。
penfe 2011-06-17
  • 打赏
  • 举报
回复
up and up

110,566

社区成员

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

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

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