各位达人:
我现在需要实现这样的一个功能,客户端发出请求,服务器端接受到请求后,就持续发送数据到客户端,客户端接受到数据后再进行处理。这里先不说客户端接收到数据后处理的问题。
就说发送和接收的问题。该如何实现呢!
我试验过如下两种方法。
第一、客户端发送一个请求,服务器接受到请求后,就不停地发送数据。然后客户端就不停地接受。什么时候,客户端不想要了,就发送一个停止发送的请求。
但我遇到的问题是:服务器在连续发送若干个数据块后,再发送数据,就会返回-1。但WSAGetLastError()却返回0。
第二、一问一答的方式,也就是,客户端发送一个请求,服务器接受到请求后,就回送一个数据块。然后客户端继续发送请求,服务器就再回送数据块。
这个方法遇到的问题是,客户端请求若干个数据块后,就接受不到数据了,为了调试,我在服务器端和客户端都写了调试输出信息,发现,客户端发送请求调用的send函数,返回值是正确的。并且服务器端也收到了这个请求,而且服务器也回送了指定大小的数据块,服务器回送数据块调用send返回值也确实是要发送的数据块的大小。但客户端就接收不到数据了,一直停在recv上。
我的环境:
win2003server+vc6.0(sp6),socket没有使用mfc里的。通信使用tcp方式。

解决方案 »

  1.   

    你这是阻塞的吧? 你在客户端开个抓包工具 客户端停在RECV()时候  抓包工具看看有没有抓到包
      

  2.   

    当然用第一中方法但我遇到的问题是:服务器在连续发送若干个数据块后,再发送数据,就会返回-1。但WSAGetLastError()却返回0
    用非阻塞方式
      

  3.   

    我搜了一下,使用非阻塞模式,应该就是用
    WSAAsyncSelect(ServerSock, m_hWnd, NETWORK_EVENT, FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE)
    这个函数来实现吧。
    那我的问题是,客户端还好说,因为客户端有窗口,当然就可以使用消息接收,也就有m_hWnd,但服务器端,我的程序是一个控制台程序,并且程序最总要最为服务来运行,怎么实现呢?现在程序写到这个份上了,不可能再改成使用CAsyncSocket了。
    我现在用的是非MFC的socket,也就是自己调用socket函数来创建SOCKET。
    给个建议吧。
      

  4.   

    非阻塞不一定就窗口吧 五种模型  最不济用select也行吧 设个超时时间
      

  5.   

    我的socket是自己封装的一个对象,都是按照阻塞模式写的,比如,为了让服务器端能接受多个客户端连接,我把accept写到线程里了,要是改成非阻塞,那改动太大了。
    能不能使用select函数,实现非阻塞呢。
    还有,socket是阻塞模式,为什么会出现我遇到的那个情况呢?
    难道阻塞模式就不能实现持续发送数据?
      

  6.   

    我看了你在另外一个帖子里面说明的情况 我想你是不是在客户端接收完数据进行处理流程上也使用了同步方式 导致客户端接收数据不及时 你可以开两个线程A,B,线程A负责接收网络数据,接收到数据后立刻将数据拷贝到一个队列里面,另外一个线程B不断从这个队列里面取出数据进行你需要进行的操作 这样应该就不会导致网络接收不及时引起错误。
      

  7.   

    谢谢楼上的建议,我想可能是因为这个原因。我的客户端接受数据,确实用的是同步处理。
    我改成异步处理接收到的数据再试验一下。
    另外,还几个问题如下:
    1、如果使用非阻塞模式,发送数据的时候,比如调用一次send发送10K(这只是我举的例子)数据,是否会出现只发送一部分的情况。我想要的结果最好是我让send发送10k,要是发送成功就因该完全发送出去,否则,就一个字节就别发送,直接返回-1。到底是哪种情况呢?
    2、非阻塞模式下,接收数据的时候,如果我指定要求接受10K的数据,会不会出现接受到数据并没有10K,而是小于10K的数字。
    我想,如果接收缓冲区里没有10K的数据可供接受,肯定返回的不会是10K,但如果接收缓冲区里有足够的数据呢?当然要想让接收缓冲区的数据足够,必须要在第一个问题上要按照我想要的那种方式发送。不知道是否是这样!
    3、之所以我有1,2两个问题,是因为服务器端每次发送数据的数据,除了实际的数据体外,每次发送都要有一个数据头,实际上是一个结构,大约有18个字节,这个结构就是自己定义的协议。并且结构里有一个成员,是指明实际的数据长度。接受端必须先接受到这个结构,然后根据结构里的数据长度,来接受实际的数据。这样接受来得数据才是有意义的。
    请指点一下!谢谢!
    主要还是对socket的工作过程和原理不理解才造成了我现在这么多的问题。
    我先把客户端接受数据按照异步处理的方法试验一下吧。
    实在不行,只能是改成非阻塞模式了。
      

  8.   

    一次发10K  TCP底层会自动分解成多次发送
    你既然有自定义了协议,接收线程接收数据完只管拷贝到数据队列里面,另外一个线程循环从数据队列里面读取最前面的数据头,取出长度,然后再读取指定长度后面的数据,如果长度不够,继续下一次循环。
      

  9.   

    数据队列其实就是一个比较大的缓冲区 比如 你定义一个 
    unsigned char *buf[1000];  //缓冲区
    unsigned int len=0;        //缓冲区里里面数据长度假设你收到的数据是unsigned char *recvdata;长度是recvlen;收到数据后
    memcpy(buf+len,recvdata,recvlen);
    len+=recvlen;当然两个线程同时访问buf和len 所以需要做线程同步 设置个mutex就差不多了 
    我先吃饭 下午联系 
        
      

  10.   

    放入还可以理解。
    那取出呢?
    取走数据后,后面的数据是不是要往前挪呀。
    能不能大致给我描述一下放数据和取数据对buf缓冲区的操作过程。
    谢谢了
      

  11.   

    unsigned char *buf[1000];  //缓冲区 
    unsigned int len=0;        //缓冲区里里面数据长度 放入数据:
    假设你收到的数据是unsigned char *recvdata;长度是recvlen; memcpy(buf+len,recvdata,recvlen); 
    len+=recvlen; 另外一个线程取出数据:
    比如数据最前面两个字节表示后面数据的长度 假设已经取出来叫datalenunsigned char *buf_temp=(unsigned char *)malloc(datalen);memcpy(buf_temp,buf,datalen);  //取出来
    memcpy(buf,buf+datalen,len-datalen);  //后面数据往前面移
    len-=datalen;由于取出放入数据线程都需要访问修改buf和len  因此要弄个互斥体来保护一下