C# 如何通过使用.net TcpClient进行通信来判断NetWorkStream何时完成
我尝试使用stream.DataAvailable来判断它是否完成,但有时该值为false,但过了一段时间它再次为true,我必须设置一个计数器并通过符号“>”来判断结束,如下所示C# 如何通过使用.net TcpClient进行通信来判断NetWorkStream何时完成,c#,.net,tcpclient,networkstream,C#,.net,Tcpclient,Networkstream,我尝试使用stream.DataAvailable来判断它是否完成,但有时该值为false,但过了一段时间它再次为true,我必须设置一个计数器并通过符号“>”来判断结束,如下所示 int connectCounter = 0; while (connectCounter < 1200) { if (stream.DataAvailable) { while (stream.DataAvailable) { byte
int connectCounter = 0;
while (connectCounter < 1200)
{
if (stream.DataAvailable)
{
while (stream.DataAvailable)
{
byte[] buffer = new byte[bufferSize];
int flag = stream.Read(buffer, 0, buffer.Length);
string strReadXML_t = System.Text.Encoding.Default.GetString(buffer);
strReadXML = strReadXML + strReadXML_t.Replace("\0", string.Empty);
}
if (strReadXML.Substring(strReadXML.Length - 1, 1).Equals(">"))
{
break;
}
}
Thread.Sleep(100);
connectCounter++;
}
int connectCounter=0;
同时(连接计数器<1200)
{
if(stream.DataAvailable)
{
while(stream.DataAvailable)
{
字节[]缓冲区=新字节[bufferSize];
int flag=stream.Read(buffer,0,buffer.Length);
string strReadXML_t=System.Text.Encoding.Default.GetString(缓冲区);
strReadXML=strReadXML+strReadXML\u t.Replace(“\0”,string.Empty);
}
if(strReadXML.Substring(strReadXML.Length-1,1).Equals(“>”)
{
打破
}
}
睡眠(100);
connectCounter++;
}
有什么好办法处理吗?谢谢 试试看。调用回调时,可以读取现有数据缓冲区,然后调用
重新开始
。这样,当收到更多数据时,您的回调将再次被调用
比如:
void DataReceived(IAsyncResult result) ///I am not sure about the parameters.
{
///read data from buffer
networkstream.BeginRead(
buffer, 0, buffer.Length,
new AsyncCallback(DataReceived),
null);
}
我认为这是一个相当不错的方法。试试。调用回调时,可以读取现有数据缓冲区,然后调用
重新开始
。这样,当收到更多数据时,您的回调将再次被调用
比如:
void DataReceived(IAsyncResult result) ///I am not sure about the parameters.
{
///read data from buffer
networkstream.BeginRead(
buffer, 0, buffer.Length,
new AsyncCallback(DataReceived),
null);
}
我认为这是一个相当不错的方法。你有几个选择。您可以使用同步、分块读取,也可以使用异步IO模式 如果只调用stream.Read(),调用将被阻塞,并永远等待(直到TCP超时),直到数据可用。看来你不想那样做。您最多需要等待120秒(1200ms*100)才能完全读取数据 大概是这样的:
private class AsyncState
{
public NetworkStream ns;
public ManualResetEvent e;
public byte[] b;
public String strReadXML;
}
public void Run()
{
TcpClient client ;//= ...
NetworkStream networkStream = client.GetStream();
byte[] buffer = new byte[1024];
var completedEvent = new ManualResetEvent(false);
networkStream.BeginRead(buffer, 0, buffer.Length,
AsyncRead,
new AsyncState
{
b = buffer,
ns = networkStream,
e = completedEvent,
strReadXML = ""
});
// do other stuff here. ...
// finally, wait 120s for the reading to complete
bool success = completedEvent.WaitOne(1200*100, false);
if (!success)
{
client.Close();
}
}
private void AsyncRead(IAsyncResult ar)
{
AsyncState state = ar as AsyncState;
int n = state.ns.EndRead(ar);
if (n == 0)
{
// no more bytes to read
// signal completion
state.e.Set();
return;
}
// state.buffer now contains the bytes read
string s = System.Text.Encoding.Default.GetString(state.b);
state.strReadXML = state.strReadXML + s.Replace("\0", string.Empty);
if (state.strReadXML.EndsWith(">"))
{
// got the "end". signal completion
state.e.Set();
return;
}
// read again
state.ns.BeginRead(state.b, 0, state.b.Length, AsyncRead, state);
}
你有几个选择。您可以使用同步、分块读取,也可以使用异步IO模式 如果只调用stream.Read(),调用将被阻塞,并永远等待(直到TCP超时),直到数据可用。看来你不想那样做。您最多需要等待120秒(1200ms*100)才能完全读取数据 大概是这样的:
private class AsyncState
{
public NetworkStream ns;
public ManualResetEvent e;
public byte[] b;
public String strReadXML;
}
public void Run()
{
TcpClient client ;//= ...
NetworkStream networkStream = client.GetStream();
byte[] buffer = new byte[1024];
var completedEvent = new ManualResetEvent(false);
networkStream.BeginRead(buffer, 0, buffer.Length,
AsyncRead,
new AsyncState
{
b = buffer,
ns = networkStream,
e = completedEvent,
strReadXML = ""
});
// do other stuff here. ...
// finally, wait 120s for the reading to complete
bool success = completedEvent.WaitOne(1200*100, false);
if (!success)
{
client.Close();
}
}
private void AsyncRead(IAsyncResult ar)
{
AsyncState state = ar as AsyncState;
int n = state.ns.EndRead(ar);
if (n == 0)
{
// no more bytes to read
// signal completion
state.e.Set();
return;
}
// state.buffer now contains the bytes read
string s = System.Text.Encoding.Default.GetString(state.b);
state.strReadXML = state.strReadXML + s.Replace("\0", string.Empty);
if (state.strReadXML.EndsWith(">"))
{
// got the "end". signal completion
state.e.Set();
return;
}
// read again
state.ns.BeginRead(state.b, 0, state.b.Length, AsyncRead, state);
}
您是否可以控制发送应用程序?如果您这样做,您可以更改发送应用程序,将
网络流
包装在二进制编写器
中,并使用.Write(string)
发送字符串长度,然后再发送字符串本身。在接收应用程序上(如上所述),您可以将网络流
包装在二进制读取器
中,并调用.ReadString()
,它将从流中读取长度,然后为您读入正确的长度字符串
如果您无法控制发送应用程序,则可以检查stream.Read()
调用的返回,因为它在流的末尾返回0-尽管这需要发送应用程序关闭套接字
另外,
stream.Read()
不能保证返回您请求的字节数,它可能返回更少的字节数。您的标志
变量实际上应该是bytesread
,然后您应该将此bytesread
变量传递给.GetString
方法。您可以控制发送应用程序吗?如果您这样做,您可以更改发送应用程序,将网络流
包装在二进制编写器
中,并使用.Write(string)
发送字符串长度,然后再发送字符串本身。在接收应用程序上(如上所述),您可以将网络流
包装在二进制读取器
中,并调用.ReadString()
,它将从流中读取长度,然后为您读入正确的长度字符串
如果您无法控制发送应用程序,则可以检查stream.Read()
调用的返回,因为它在流的末尾返回0-尽管这需要发送应用程序关闭套接字
另外,
stream.Read()
不能保证返回您请求的字节数,它可能返回更少的字节数。您的标志
变量实际上应该是bytesread
,然后您应该将此bytesread
变量传递给.GetString
方法。这些代码中仍然存在一个问题。int n=state.ns.EndRead(ar);如果(n==0){//没有更多的字节要读取//信号完成状态.e.Set();return;}当n==0时,method返回,但我不能简单地判断n==0没有更多的字节要读取。因为有时流上会有一点中断,然后它再次传输数据。我不知道确切的原因。可能是bandwith的原因。这些代码中还有一个问题。int n=state.ns.EndRead(ar);如果(n==0){//没有更多的字节要读取//信号完成状态.e.Set();return;}当n==0时,method返回,但我不能简单地判断n==0没有更多的字节要读取。因为有时流上会有一点中断,然后它又传输数据了。我不知道确切的原因。也许是bandwith的原因。