我有一个简单的tcp / ip聊天程序与服务器和客户端。我第一次发送数据包时,它会发送到客户端,但在NetworkStream.Read期间,它会停止执行并且不会抛出异常。我发送的下一个数据包被完美地读取和处理。我注意到的另一个奇怪的事情是MyNetworkStream.DataAvailable总是假的,即使我从服务器获取信息,所以我必须放置一个调试符号并跳过它。我希望我可以发布所有代码,但它很长,所以我会发布我读写网络流的地方。
public void Listen(int byteLength)
{
var buffer = new byte[byteLength];
MySocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(Read), buffer);
}
private void Read(IAsyncResult ar)
{
while (MySocket.Connected)
{
MyNetworkStream = new NetworkStream(MySocket);
var buffer = new byte[((byte[])ar.AsyncState).Length];
if (!MyNetworkStream.DataAvailable)
throw new Exception("Data not available");
MyNetworkStream.Read(buffer, 0, buffer.Length); <------Here it stops execution without throwing an exception
string content = Encoding.ASCII.GetString(buffer);
if(OnRead == null)
continue;
var e = new CommandEventArgs( null, content);
Control target = null;
if (OnRead.Target is Control)
target = (Control)OnRead.Target;
if (target != null && target.InvokeRequired)
target.Invoke(OnRead, this, e);
else
OnRead(this,e);
}
}
public void Write(string message)
{
try
{
var buffer = Encoding.ASCII.GetBytes(message);
MySocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, null);
if (OnWrite != null)
{
var target = (Control)OnWrite.Target;
if (target != null && target.InvokeRequired)
{
target.Invoke(OnWrite, this, new EventArgs());
}
else
{
OnWrite(this, new EventArgs());
}
}
}
catch
{
}
}
答案 0 :(得分:2)
BeginReceive
异步等待消息并填充缓冲区。然后,您从套接字开始同步读取,覆盖过程中的第一条消息。
你应该调用EndReceive
来返回读取的字节数,然后在尝试读取更多字节之前处理你的缓冲区。
答案 1 :(得分:1)
我不确定它是否与问题直接相关,但您使用的Read
方法错误。您正在将数据读入缓冲区,但是您忽略了实际读取了多少数据,假设Read
调用始终返回您请求的数据量,因此您正在解码整个缓冲区,尽管它可能未完全填充
获取Read
调用的返回值,以便您知道实际填充了多少缓冲区数据:
int len = MyNetworkStream.Read(buffer, 0, buffer.Length);
string content = Encoding.ASCII.GetString(buffer, 0, len);
答案 2 :(得分:0)
您需要实现EndRecieve才能从流中获取完整数据。从MSDN中查看以下示例:
public static void Read_Callback(IAsyncResult ar){
StateObject so = (StateObject) ar.AsyncState;
Socket s = so.workSocket;
int read = s.EndReceive(ar);
if (read > 0) {
so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read));
s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0,
new AsyncCallback(Async_Send_Receive.Read_Callback), so);
}
else{
if (so.sb.Length > 1) {
//All of the data has been read, so displays it to the console
string strContent;
strContent = so.sb.ToString();
Console.WriteLine(String.Format("Read {0} byte from socket" +
"data = {1} ", strContent.Length, strContent));
}
s.Close();
}
}