小弟刚刚接触通信这块,对这块还不懂,所以想请教几个问题:
1、tcp在数据接收时,调用TcpSocket.Receive(buff);方法,是缓冲区满了进行处理,还是接收一条指令就处理?
    举例:我设置缓冲区为1K,一条指令为600个字节的情况下,调用TcpSocket.Receive(buff);方法,缓冲区内只有1条指令,还是会将下条指令的一部分也存储在缓冲区内然后处理??因为如果是后面这种情况的话,肯定要将多余的和后面的指令进行合并来处理
    
    另外udp是什么情况?    因为小弟不是计算机专业,也不是通信专业,可以说对通信这块外行,能否推荐本实用的入门书?
希望各位大虾不吝赐教,先行谢过了。
    

解决方案 »

  1.   

    udp 是面向无连接的通信协议。。
      

  2.   

    TCP情况是每次读取的字节数不确定,有个边界问题TCP没这个问题。
      

  3.   


    udp是无连接的,那么等于缓冲区没每次都是一个包吗??
      

  4.   

    最好每次都处理,下一次接收会覆盖掉上次的数据,即时将接收的数据提交给应用层,如果你确定收到的不是一个完成的数据包,可以为当前会话建立缓冲区,将其移动到这个缓冲区。
    tcp和udp都为传输层协议。
    tcp提供的是面向连接的,可靠的字节流服务,tcp首先必须建立通讯链路。
    udp提供的是一个简单的面向数据报的运输层协议,不提供可靠性,它只是把应用程序传给ip层的数据报发送出去,但是并不能保证它们能到达目的地.
    udp虽然不安全,但不需要维护链路,可以节省服务器资源。好像udp速度也比较快。
      

  5.   


    那就是说,读到的数据,肯能不是刚好1个完整的包,是吗?这是tcp情况,还是UDP也是这样?
      

  6.   

    udp 是面向无连接的通信协议。。
      

  7.   

    我之前写的简单通讯是这样分析发送来的数据的,给你参考下.............if (_tcpl.Pending()) //如果有挂起的请求则分析数据
      {
      byte[] buf = new byte[5];
      byte[] tempBuf;
      int count = 0;
      string userName = "", msg = "";  Socket newSocket = _tcpl.AcceptSocket();  if (newSocket.Available > 0)//如果有数据则获取
      {  
      //客户端按自己定的格式发送 例如发送"aa  1    4test" 
      //"aa"为最初识别码, "   1"为用户名, "    4"为后面字串的长度,"test"为请求内容
      newSocket.Receive(buf, 0, 5, SocketFlags.None);
      msg = Encoding.ASCII.GetString(buf, 0, 5).Trim('\0');//先获取前5位
      if (msg.IndexOf("aa") >= 0) //头两位为aa则格式正确继续处理  
      {
      userName = msg.Substring(2, 3);//获取用户名
      newSocket.Receive(buf, 0, 5, SocketFlags.None);//继续取后5位
      msg = Encoding.ASCII.GetString(buf, 0, 5).Trim('\0');
      count = Convert.ToInt32(msg);//得到串的长度  tempBuf = new byte[count];
      newSocket.Receive(tempBuf, 0, count, SocketFlags.None);
      msg = Encoding.ASCII.GetString(tempBuf, 0, count).Trim('\0');//根据得到的长度获取最后的内容if (msg == "test")
    {
    //实际操作
    }}
    }}
      

  8.   

    下一条指令不会和上一条合并udp 就是一个无状态的
    将信息发给网络上所有电脑
    至于有没有被接收到 就不去管了
    tcp 不一样 只有互相之间建立连接才可以通信
      

  9.   


    电脑怎知道什么叫做“一条指令”?对于tcp,粘包是正常现象,因为tcp(看看rtf文档)就是这样设计的。对于.net所写的服务端,接收缓冲设置为1k未免太小气了,设置为32k也不为过。如果你的服务面向大规模的网络,就好象互联网这样,那么可以考虑短连接而不是长连接方式。如果只是连接树木很有限的一些固定的客户端,则可以考虑长连接方式(因为这样可以直接突破nat限制)。
      

  10.   

    UDP每次接收到是一个整包,而TCP收到的是流数据,可能含多个包
      

  11.   

    多谢LS几位了我现在想知道在调用 TcpSocket.Receive(buff);(buff为缓冲区)这个方法的时候,是会一直把缓冲区写满吗?哪位大虾可以讲讲这个机制??
    因为我的包是定义了包头 包长 校验 和包尾的,缓冲区内会不会出现半个包的问题?打比方:缓冲区设置了10个字节,而一个包有4个字节,那么最后面2个字节会不会有内容?也就是说以个包会不会在2次缓冲区内出现??谢谢啦
      

  12.   


    两种情况(当然是指正常情况下),会导致TcpSocket.Receive方法返回
    1. 接收到的数据被读取完了
    2. TcpSocket.Receive方法里的buff数组填满了也就是 TcpSocket.Receive 方法接收数据,每次最多只能接收 buff 长度的数据。至于真实接收了多少个字节,就要看  TcpSocket.Receive 方法返回的数值。
    打比方:缓冲区设置了10个字节,而一个包有4个字节,那么最后面2个字节会不会有内容?也就是说以个包会不会在2次缓冲区内出现??你所说的缓冲区是什么缓冲区?
    不太明白 ,这样说吧TcpClient.Receive里的
    buff 字节数组长度是100
    ^
    |
    |
        系统缓冲区
    ^
    |
    |
      客户端发送数据这样,你写一个循环如下int len = TcpClient.Receive(buff);
    byte[] PackageData = new byte[最在的包大小+buff.Length];
    int PackageDataLen = 0;   // PackageData数组还有多少的数据
    while( len > 0 ) // 说明本次有取到数据,如果长度为0,说明缓冲区里没有数据可以读了
    {
    //把buff从0开始长度为len的字节复制到PackageData数组从PackageDataLen开始的下标后面(包括PackageDataLen这个下标)
    if(判断你的PackageData数组中有没有包含一个完整自定义协议包)
    {//有
    //取出一个包的数据组成一个包对象,加入到队列
    int PkgLen = 刚取走的包所包含的字节数
    //把PackageData数组头PkgLen长度的字节全部删除(这步也可以不做,可以采用后面的数据直接覆盖上来)
    //然后把从PkgLen下标开始的数据全部移到头部开始的下标处(顺序前移到下标 0 处)
    PackageDataLen = PackageDataLen + len - PkgLen // 设置现在PackageData数组里还剩的数据长度
    }
    else
    {
    PackageDataLen = PackageDataLen + len;
    } // 再从缓存区取数据,
    len = TcpClient.Receive(buff);
    }
      

  13.   

    UDP 不必建立连接,有可能第二条报文比第一条报文先到
    TCP 是建立连接的,按数据发送顺序接收的