TcpListener接收数据不全?
下面是接收代码的异步类,但是发现接收数据不全,如果发送的数据比较多的话;
protected void AcceptClient(IAsyncResult ar)
{
try
{
TcpListener tcpListener = (TcpListener)ar.AsyncState;
TcpClient tcpClient = tcpListener.EndAcceptTcpClient(ar);
NetworkStream networkStream = tcpClient.GetStream();
StreamReader streamReader = new StreamReader(networkStream);
string content = streamReader.ReadToEnd();
rtbxContent.Invoke(new MethodInvoker(delegate
{
rtbxContent.Text = "";
rtbxContent.Text = content;
}));
networkStream.Close();
tcpClient.Close();
//tcpListener.Stop();
tcpListener.BeginAcceptTcpClient(new AsyncCallback(AcceptClient), tcpListener);
//这样写也是可以的,只是要等到一个线程结束之后才会开始接收下一个请求
}
catch (Exception ex)
{
MessageBox.Show("出错了: \n" + ex.Message, "错误");
}
}
------解决方案--------------------如果数据量大的话不能只是一次接收,你应该循环接收啊。网上代码有很多呢
------解决方案--------------------怎么可能使用 StreamReader 来判断“结束”呢?通讯是在底层被拆成100多个字节一个小数据包逐步传送的,通讯消息的结束标志是用通讯内容来标记的,就好象开会发言时说“我说完了”来表示发言结束,而不是用0.5秒钟停顿来代表发言结束。
------解决方案--------------------与之相关的,读取 networkStream = tcpClient.GetStream() 中的数据时也应该使用异步 BeginRead 方法,因为即使客户端是一次Send 100K 字节,服务器端也可能需要分50次接收完全,中间有短暂的停顿,这个时间阻塞这去同步Read,比较浪费资源。
你可以使用一个 MemoryStream,将异步读取的数据写到它里边。然后当读取到消息结束时,才取出累积的数据,统一处理。
------解决方案--------------------TCP客户端->
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
namespace TCPClient
{
public partial class TCPClient : Form
{
public TCPClient()
{
InitializeComponent();
}
TcpClient tc = null;
Thread td = null;
private void button1_Click(object sender, EventArgs e)
{
tc = new TcpClient();
tc.Connect("127.0.0.1",10000);
td = new Thread(new ThreadStart(getmges));
td.IsBackground = true;
td.Start();
}
NetworkStream ns = null;
public void getmges()
{
ns = tc.GetStream();
while (true)
{
if (ns.DataAvailable)
{
byte[] bt = new byte[1000];
ns.Read(bt,0,tc.Available);
string str = Encoding.UTF8.GetString(bt);
MessageBox.Show(str);
}
}
}
private void button2_Click(object sender, EventArgs e)
{
string str = textBox1.Text;
byte[] bt = Encoding.UTF8.GetBytes(str);
ns = tc.GetStream();
ns.Write(bt,0,bt.Length);
}
}
}