首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

【win网络编程】socket中的recv拥塞和select的用法

2012-11-23 
【win网络编程】socket中的recv阻塞和select的用法转载请注明出处:作者 kikilizhm在编写ftp客户端程序时,在

【win网络编程】socket中的recv阻塞和select的用法

转载请注明出处:作者 kikilizhm


在编写ftp客户端程序时,在联通后使用recv函数进行接收欢迎信息时,需要申请内存进行接收数据保存,一次读取成功,但是由于一个随机的ftp服务端在说,欢迎信息的大小是不知道的,所以在尝试使用死循环,在阅读recv的说明时讲到返回值即是接收到的字节数,那么返回0的时候就代表结束了,实践发现recv是个阻塞函数,在连接不断开的情况下,会一直处于阻塞状态,也不会返回0.也就是说程序不能这么一直读,如果对端连接没有关闭,则在没有数据的情况下,调用recv会阻塞,如果对端关闭连接,则立即返回0.

所以就需要使用到select函数来操作。

MSDN中对select的介绍连接为:ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/winsock/winsock/select_2.htm

select的功能为检测一个或者多个socket是否可读或者可写,或者有错误产生。根据设置可以处于阻塞、非阻塞、等待固定时间返回。

原型:

select Function

The select function determines the status of one or more sockets, waiting if necessary, to perform synchronous I/O.

Parameters
nfds

Ignored. The nfds parameter is included only for compatibility with Berkeley sockets.

忽略。nfds参数在这里只是为了和伯克利套接字相兼容。(这个参数在linux中有意义)

readfds

Optional pointer to a set of sockets to be checked for readability.

指向一组等待判断可读性的socket的指针,可不设置。

writefds

Optional pointer to a set of sockets to be checked for writability.

指向一组等待判断可写性的socket的指针,可不设置。

exceptfds

Optional pointer to a set of sockets to be checked for errors.

和上面两个一样,指向待检测是否发生错误的一组socket的指针,可不设置。

timeout

Maximum time for select to wait, provided in the form of a TIMEVAL structure. Set the timeout parameter to null for blocking operations.

select函数最大等待时间,使用TIMEVAL结构体。设置为NULL时阻塞。

TIMEVAL结构体定义如下:

#include<stdio.h>#include <winsock2.h>#include <string.h>int main(void){    SOCKET fp;    FILE * ffp;    struct fd_set rfds;    struct sockaddr_in ipadd;    struct timeval timeout = {3,0};    char * readbuff[10] = {0};    WSADATA wData;    WSAStartup(0x0202,&wData);    fp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    memset(&ipadd, 0, sizeof(struct sockaddr_in));    ipadd.sin_family = AF_INET;    ipadd.sin_addr.s_addr = inet_addr("192.168.1.101");    ipadd.sin_port = htons(21);    if(0 != connect(fp, &ipadd, sizeof(struct sockaddr_in)))    {        printf("\r\nerror");    }    ffp = fopen("test.txt", "rw+");    int ret;    while(1)    {        FD_ZERO(&rfds);  /* 清空集合 */        FD_SET(fp, &rfds);  /* 将fp添加到集合,后面的FD_ISSET和FD_SET没有必然关系,这里是添加检测 */        ret=select(0, &rfds, NULL, NULL, &timeout);        printf("\r\nselect ret = %d",ret);        if(0 > ret)        {                closesocket(fp);                fclose(ffp);                return -1;        }        else if(0 == ret)        {            break;        }        else        {            if(FD_ISSET(fp,&rfds))  /* 这里检测的是fp在集合中是否状态变化,即可以操作。 */            {                recv(fp, readbuff, 9, 0);                // printf("\r\n%s",readbuff);                fputs(readbuff, ffp);                memset (readbuff,0,10);            }        }    }    printf("\r\nread successful!");    fclose(ffp);    closesocket(fp);}



热点排行