图像检索服务器编写问题记录——TCP粘包了!!!

服务器端在选出匹配度高的图片后,将多个图片发送给客户端,结果客户端除了第一个图片正常外,其余都是乱码;运气好时,能有两个是正确的。打印客户端接收数据如下

136199
���
����l~,s8�[��:��<���zӓNjxn% �펿*% N��K��A�pGS�����[�`7�aC��������94H�&2�;��2�1��MS';f�J�6�4C��s�EHLȈLr
��n5��R��SؒJ�?L���il���� �b��5/\���
>t���
       u�.bIc�9M���o��c�T1)\$�dLm��[�b'
                                        1�y�j%
                                              �qtU��grß��>٩��㑂F��4���)�l��ǰ$o���E`���Q��gަ2�2��y�	۽ ;�Po��Q$�p�8�@�s�v�'ޥ�r9�9�
�܁��d�E-~ �
             H��P,�B��j��
��?�n��4f&
      �Y8RzW&5v��;(?`�~d`�GyrB걝v~t�

���!)����
i*]@`�B���IvT4��q{Xo-��"�5&@=��U_2H��(�(:�v�z�p� ���ԒJ��*��63�
#m�I9�3�Y��_.��
0΁����U���DYW
��nHϰP�����6۽C�d�8�Ljd�w�6<�_�D~
����ǷN�Vi|�)�n@}��O^F�e8; �21�T���$�$؜S^_0
                                          @�m��Vyf$�k�l���;`�)��$�9
i&�N�1����"�&W���*��Z���[FG����~t
  �a�TP,
        ��T����m�\��*-�b��� �b�dc�k�_!#<��Ү�|;*��D|L�����Q4d��1�3�̊W'8�'��a|;N
%Y
  +.s(Qn\����6r�
                  1䶪�m�"�A
�)��t��%ǭA�B7?*��@d�]L�0F��D�B	�
                                         0:��[�4
                                                 v�8
�)�c���C9B�X�2	��������FL��;{w�U��ԃ������
(�	T0v���ē���,���%ٺ�B�^�ސcI�LzS.fD	�@�]������['Y#��@�]�~&�m�����=j�A~73}�"�pϺ�O-�Ö�hV���:���

DS��P̪ˍ�^�:}/ٯZ(ݘ��C+�{���h�m���
                                     lBF�PV�����W��?올��+'ub0��'�@�k>���߬�-Ex��(�T�O#If�Hc<�΅�+
��P��M�U:U-��1�ZW �6�`F�6_+�i-&��H�\
�D-N���V�H�I����3ȃ���l�����
,w�6'
=���5��
         4m��A�o�j�C�O��{��o���'&��Yo�x���-�í�G*�q��t���ҫ^�����>($����>�^ǂY�;y4�v�$���%oJ��*�\(�
                       }�E��w���\;1�3�@x�j�E42JV6��m|����՘���Ct��G�d�3���j��<K��Fx�g`�c�`�NN~Y�\Wd��-<Xڀ(T�~.t�T:����Vn-��S��`)�8�
#��
 �����
2�dw'�Vo����å�fM
rd;�Z������9���&��Ջ�
                    ø���uL���W��zo[G����ð7�
���;%��c&��'��=�1/�]�qZx�Yv$��{�Z��Â(/YmfȎFV�(>�jבZ�<ߎK���ozs����=+G�
��W���#gVw���yVJ�
                 9��KF�q�l�,0<����U��m���Ÿv�LJ��'r}s����x��Y�G%ǘ	�e_�����rS+�pZ�q�-���?p�d
z��ù�Ӊ
      ��̬G}G����}O�3��x,�s��ZP���o6@Ԝ"Y��qY��4
                                                o4��BFv�]�43����E�c��e�ܖӬ�
72�Ɇ��
p̧u8�P�$q&�!q���T���v@��ޜ��o"K�W|
=w �c�7MQ�ea�@؏z� ��������%�LR?
                                 j�
�sl��#:�c�ڗ���K<
�����[Y����f���F�%�+��TM}�#���l�W�W�u
                                           ��mT�_����ٰ��5m��Z�~c�
�qǧ+��|�2j������j"���a���z�:{��nYX�"�S�mר��Az&��p8�KH\�Yd�f;�=:t�R�47�}��L\�唐H��;v�VxU�O���/"�G�Vy���ށM$���f�
                                     RD�Lh�P�=7�S��7���.ldDVQ2��E�y��׹���kĠ�����b��[���g��׶�qk8�Dd;6�SϞ3����{ø�m:��P�[�?J�hz�
BُP8ڝn�}����<U���ZZDՋ[��#��d��LZ7g
�I�!��R�ƿ�h}���D-��X\s��ի�Kh4�*I BX�F�$q�Pۓ*�	Ŧ�ݖh��4���،�N
��                                                               f�/��(Ƶ�p��#��
�����B��ö�N�d��y!Y�i�\�Cט����Z.�
                                 	y�ow��dq�^@c:{��8/�g){
��rr�_���S[�x�xL�tH����U���I �<'r[�#-�}*���b�#P��1T{�r�ԉ�n7Ƈ^��$Q

<F

删了一部分,但明确的是,只有第一个文件的文件大小136199是明确接收到了,其他均是乱码。

上上下下检查代码,没发现错。

在服务器发送一张图片后加了个sleep(3),结果客户端全部成功接收了。靠!!!!

脑海中出现了TCP粘包这个久远的词汇。于是给sockfd加上了TCP_NODELAY···

但是在服务器端设置TCP_NODELAY后还是无法正确接收包。检查后,发现客户端程序写错了。

原先客户端程序是for{read socketfd接收10bit的长度,read socketfd接收20bit的文件名,read socketfd接收文件}这样在写完第一个文件之后,其余数据全部被丢弃了,所以才会导致余下的包无法正确接收。


发送多个文件是:TCP===》IP====》TCP的过程,在发送端关闭Nagle算法的同时(一次一次发,不要小包打成大包一起发),也许要确保接收端一次一次接收。我的情况属于接收端没有正确接收+发送端没关闭Nagle算法。


以下转自:http://www.cnblogs.com/qiaoconglovelife/p/5733247.html

1 什么是粘包现象

  TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

2 为什么出现粘包现象

  (1)发送方原因

  我们知道,TCP默认会使用Nagle算法。而Nagle算法主要做两件事:1)只有上一个分组得到确认,才会发送下一个分组;2)收集多个小分组,在一个确认到来时一起发送。

  所以,正是Nagle算法造成了发送方有可能造成粘包现象。

  (2)接收方原因

  TCP接收到分组时,并不会立刻送至应用层处理,或者说,应用层并不一定会立即处理;实际上,TCP将收到的分组保存至接收缓存里,然后应用程序主动从缓存里读收到的分组。这样一来,如果TCP接收分组的速度大于应用程序读分组的速度,多个包就会被存至缓存,应用程序读时,就会读到多个首尾相接粘到一起的包。

3 什么时候需要处理粘包现象

  (1)如果发送方发送的多个分组本来就是同一个数据的不同部分,比如一个很大的文件被分成多个分组发送,这时,当然不需要处理粘包的现象;

  (2)但如果多个分组本毫不相干,甚至是并列的关系,我们就一定要处理粘包问题了。比如,我当时要接收的每个分组都是一个有固定格式的商品信息,如果不处理粘包问题,每个读进来的分组我只会处理最前边的那个商品,后边的就会被丢弃。这显然不是我要的结果。

4 如何处理粘包现象

  (1)发送方

  对于发送方造成的粘包现象,我们可以通过关闭Nagle算法来解决,使用TCP_NODELAY选项来关闭Nagle算法。

  (2)接收方

  遗憾的是TCP并没有处理接收方粘包现象的机制,我们只能在应用层进行处理。

  (3)应用层处理

  应用层的处理简单易行!并且不仅可以解决接收方造成的粘包问题,还能解决发送方造成的粘包问题。

  解决方法就是循环处理:应用程序在处理从缓存读来的分组时,读完一条数据时,就应该循环读下一条数据,直到所有的数据都被处理;但是如何判断每条数据的长度呢?

  两种途径:

    1)格式化数据:每条数据有固定的格式(开始符、结束符),这种方法简单易行,但选择开始符和结束符的时候一定要注意每条数据的内部一定不能出现开始符或结束符;

    2)发送长度:发送每条数据的时候,将数据的长度一并发送,比如可以选择每条数据的前4位是数据的长度,应用层处理时可以根据长度来判断每条数据的开始和结束。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值