日期:2014-05-18  浏览次数:20924 次

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);
}
}
}