我有一个类,它必须使用Silverlight4中的套接字发送和接收数据。
它必须实现一个预先存在的接口,所以有些事情可能看起来有点奇怪,但是
这里是:
public class TcpDataTransportClient : IDataTransportService
{
private const string TCP_ADDRESS_SETTING = "tcpaddress";
private const string TCP_PORT_SETTING = "tcpport";
private static ManualResetEvent clientConnected = new ManualResetEvent(false);
private static ManualResetEvent clientDataReceived = new ManualResetEvent(false);
private static ManualResetEvent clientDataSent = new ManualResetEvent(false);
private Dictionary<string, object> settings = new Dictionary<string, object>();
private IDataEncapsulator dataEncapsulator;
private IDataCollector dataCollector;
private Socket client;
private SocketAsyncEventArgs clientArgs;
public event DataReceivedHandler OnDataReceived;
public event DataSentHandler OnDataSent;
public TcpDataTransportClient()
{
}
public Dictionary<string, object> Settings
{
get
{
return this.settings;
}
set
{
this.settings = value;
}
}
public IDataEncapsulator DataEncapsulator
{
get
{
return this.dataEncapsulator;
}
set
{
this.dataEncapsulator = value;
}
}
public void Start(IDataCollector dataCollector)
{
this.dataCollector = dataCollector;
clientArgs = new SocketAsyncEventArgs();
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientArgs.Completed += clientArgs_Completed;
clientArgs.UserToken = client;
clientArgs.RemoteEndPoint = GetIPEndPoint();
client.ConnectAsync(clientArgs);
clientConnected.WaitOne();
}
private IPEndPoint GetIPEndPoint()
{
IPAddress ipAddress;
int tcpPort;
if (!IPAddress.TryParse(settings[TCP_ADDRESS_SETTING].ToString(), out ipAddress))
throw new ArgumentException(String.Format("Invalid setting for IP Address: '{0}'", TCP_ADDRESS_SETTING));
if (!int.TryParse(settings[TCP_PORT_SETTING].ToString(), out tcpPort))
throw new ArgumentException(String.Format("Invalid setting for TCP Port: '{0}'", TCP_PORT_SETTING));
return new IPEndPoint(ipAddress, tcpPort);
}
void clientArgs_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");
}
}
private void ProcessConnect(SocketAsyncEventArgs e)
{
if (e.SocketError != SocketError.Success)
{
throw new SocketException((int)e.SocketError);
}
else
{
clientConnected.Set();
}
}
private void ProcessReceive(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
var socket = e.UserToken as Socket;
var response = dataCollector.Collect(e.Buffer);
if (response != null)
{
if (this.OnDataReceived != null)
this.OnDataReceived(response);
clientDataReceived.Set();
}
else
{
bool willRaiseEvent = socket.ReceiveAsync(clientArgs);
if (!willRaiseEvent)
ProcessReceive(e);
}
}
else
{
throw new SocketException((int)e.SocketError);
}
}
private void ProcessSend(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
var socket = e.UserToken as Socket;
if (OnDataSent != null)
OnDataSent(clientArgs.Buffer);
clientDataSent.Set();
clientDataReceived.Reset();
bool willRaiseEvent = socket.ReceiveAsync(e);
if (!willRaiseEvent)
ProcessReceive(e);
clientDataReceived.WaitOne();
}
else
{
throw new SocketException((int)e.SocketError);
}
}
public void Stop()
{
client.Shutdown(SocketShutdown.Send);
client.Close();
client.Dispose();
clientArgs.Dispose();
}
public void Write(byte[] data)
{
clientDataSent.Reset();
clientArgs.SetBuffer(data, 0, data.Length);
bool willRaiseEvent = client.SendAsync(clientArgs);
if (!willRaiseEvent)
ProcessSend(clientArgs);
clientDataSent.WaitOne();
}
}
这里的想法是,每个请求(发送数据)总是由一个响应(接收数据)来响应,并且只要您不断开连接并创建一个新的连接,它就可以正常工作。
例如:
client.Connect();
client.ClearConfiguration(1);
var status = client.RequestStatusDetails(1);
client.Disconnect();
此代码发送多个请求,并接收每个请求的答案。
但是,如果您再次运行相同的代码(或在循环中),则会建立连接。
但一旦代码达到这一点:
public void Write(byte[] data)
{
clientDataSent.Reset();
clientArgs.SetBuffer(data, 0, data.Length);
bool willRaiseEvent = client.SendAsync(clientArgs);
if (!willRaiseEvent)
ProcessSend(clientArgs);
clientDataSent.WaitOne();
}
将为client.sendasync(clientargs)引发异常;
这是例外:
异步套接字操作是
正在使用此
SocketAsyncEventArgs实例
但是,如果在该语句前面放置一个断点,
让VS2010在其上中断,然后继续调试它工作正常。
我真的不知道是什么导致了这个问题,
没有其他信息。
有什么建议吗?