当前位置:天才代写 > tutorial > C语言/C++ 教程 > Windows Socket API利用履历

Windows Socket API利用履历

2017-11-06 08:00 星期一 所属: C语言/C++ 教程 浏览:1062

副标题#e#

本文是我在举办MS-Windows、HP-Unix网络编程的实践进程中总结出来的一些履历,仅供各人参考。本文所谈到的Socket函数假如没有出格说明,都是指的Windows Socket API。

一、WSAStartup函数

int WSAStartup(
    WORD wVersionRequested, 
    LPWSADATA lpWSAData 
   );

利用Socket的措施在利用Socket之前必需挪用WSAStartup函数。该函数的第一个参数指明措施请求利用的Socket版本,个中高位字节指明副版本、低位字节指明主版本;操纵系统操作第二个参数返回请求的Socket的版本信息。当一个应用措施挪用WSAStartup函数时,操纵系统按照请求的Socket版原来搜索相应的Socket库,然后绑定找到的Socket库到该应用措施中。今后应用措施就可以挪用所请求的Socket库中的其它Socket函数了。该函数执行乐成后返回0。

例:如果一个措施要利用2.1版本的Socket,那么措施代码如下

wVersionRequested = MAKEWORD( 2, 1 );

err = WSAStartup( wVersionRequested, &wsaData );

二、WSACleanup函数

int WSACleanup (void);

应用措施在完成对请求的Socket库的利用后,要挪用WSACleanup函数来清除与Socket库的绑定而且释放Socket库所占用的系统资源。

三、socket函数

SOCKET socket(
    int af,    
    int type,   
    int protocol 
   );

应用措施挪用socket函数来建设一个可以或许举办网络通信的套接字。第一个参数指定应用措施利用的通信协议的协议族,对付TCP/IP协议族,该参数置PF_INET;第二个参数指定要建设的套接字范例,流套接字范例为SOCK_STREAM、数据报套接字范例为SOCK_DGRAM;第三个参数指定应用措施所利用的通信协议。该函数假如挪用乐成绩返回新建设的套接字的描写符,假如失败就返回INVALID_SOCKET。套接字描写符是一个整数范例的值。每个历程的历程空间里都有一个套接字描写符表,该表中存放着套接字描写符和套接字数据布局的对应干系。该表中有一个字段存放新建设的套接字的描写符,另一个字段存放套接字数据布局的地点,因此按照套接字描写符就可以找到其对应的套接字数据布局。每个历程在本身的历程空间里都有一个套接字描写符表可是套接字数据布局都是在操纵系统的内核缓冲里。下面是一个建设流套接字的例子:


#p#副标题#e#

struct protoent *ppe;
     ppe=getprotobyname("tcp");
     SOCKET ListenSocket=socket(PF_INET,SOCK_STREAM,ppe->p_proto);

四、closesocket函数

int closesocket(
    SOCKET s 
   );

closesocket函数用来封锁一个描写符为s套接字。由于每个历程中都有一个套接字描写符表,表中的每个套接字描写符都对应了一个位于操纵系统缓冲区中的套接字数据布局,因此有大概有几个套接字描写符指向同一个套接字数据布局。套接字数据布局中专门有一个字段存放该布局的被引用次数,即有几多个套接字描写符指向该布局。当挪用closesocket函数时,操纵系统先查抄套接字数据布局中的该字段的值,假如为1,就表白只有一个套接字描写符指向它,因此操纵系统就先把s在套接字描写符表中对应的那条表项排除,而且释放s对应的套接字数据布局;假如该字段大于1,那么操纵系统仅仅排除s在套接字描写符表中的对应表项,而且把s对应的套接字数据布局的引用次数减1。

closesocket函数假如执行乐成绩返回0,不然返回SOCKET_ERROR。

五、send函数

int send(
    SOCKET s,       
    const char FAR *buf, 
    int len,        
    int flags       
   );

岂论是客户照旧处事器应用措施都用send函数来向TCP毗连的另一端发送数据。客户措施一般用send函数向处事器发送请求,而处事器则凡是用send函数来向客户措施发送应答。该函数的第一个参数指定发送端套接字描写符;第二个参数指明一个存放应用措施要发送数据的缓冲区;第三个参数指明实际要发送的数据的字节数;第四个参数一般置0。这里只描写同步Socket的send函数的执行流程。当挪用该函数时,send先较量待发送数据的长度len和套接字s的发送缓冲区的长度,假如len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;假如len小于可能便是s的发送缓冲区的长度,那么send先查抄协议是否正在发送s的发送缓冲中的数据,假如是就期待协议把数据发送完,假如协议还没有开始发送s的发送缓冲中的数据可能s的发送缓冲中没有数据,那么send就较量s的发送缓冲区的剩余空间和len,假如len大于剩余空间巨细send就一直期待协议把s的发送缓冲中的数据发送完,假如len小于剩余空间巨细send就仅仅把buf中的数据copy到剩余空间里(留意并不是send把s的发送缓冲中的数据传到毗连的另一端的,而是协议传的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里)。假如send函数copy数据乐成,就返回实际copy的字节数,假如send在copy数据时呈现错误,那么send就返回SOCKET_ERROR;假如send在期待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。要留意send函数把buf中的数据乐成copy到s的发送缓冲的剩余空间里后它就返回了,可是此时这些数据并不必然顿时被传到毗连的另一端。假如协议在后续的传送进程中呈现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的Socket函数在执行的最开始总要先期待套接字的发送缓冲中的数据被协议传送完毕才气继承,假如在期待时呈现网络错误,那么该Socket函数就返回SOCKET_ERROR)

#p#副标题#e#

留意:在Unix系统下,假如send在期待协议传送数据时网络断开的话,挪用send的历程会吸收到一个SIGPIPE信号,历程对该信号的默认处理惩罚是历程终止。

六、recv函数

#p#分页标题#e#

 int recv(
    SOCKET s,    
    char FAR *buf, 
    int len,    
    int flags    
   );

岂论是客户照旧处事器应用措施都用recv函数从TCP毗连的另一端吸收数据。该函数的第一个参数指定吸收端套接字描写符;第二个参数指明一个缓冲区,该缓冲区用来存放recv函数吸收到的数据;第三个参数指明buf的长度;第四个参数一般置0。这里只描写同步Socket的recv函数的执行流程。当应用措施挪用recv函数时,recv先期待s的发送缓冲中的数据被协议传送完毕,假如协议在传送s的发送缓冲中的数据时呈现网络错误,那么recv函数返回SOCKET_ERROR,假如s的发送缓冲中没有数据可能数据被协议乐成发送完毕后,recv先查抄套接字s的吸收缓冲区,假如s吸收缓冲区中没有数据可能协议正在吸收数据,那么recv就一直期待,只到协议把数据吸收完毕。当协议把数据吸收完毕,recv函数就把s的吸收缓冲中的数据copy到buf中(留意协议吸收到的数据大概大于buf的长度,所以在这种环境下要挪用屡次recv函数才气把s的吸收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的吸收数据是协议来完成的),recv函数返回其实际copy的字节数。假如recv在copy时堕落,那么它返回SOCKET_ERROR;假如recv函数在期待协议吸收数据时网络间断了,那么它返回0。

留意:在Unix系统下,假如recv函数在期待协议吸收数据时网络断开了,那么挪用recv的历程会吸收到一个SIGPIPE信号,历程对该信号的默认处理惩罚是历程终止。

#p#副标题#e#

七、bind函数

int bind(
    SOCKET s,             
    const struct sockaddr FAR *name,  
    int namelen            
   );

当建设了一个Socket今后,套接字数据布局中有一个默认的IP地点和默认的端标语。一个处事措施必需挪用bind函数来给其绑定一个IP地点和一个特定的端标语。客户措施一般不必挪用bind函数来为其Socket绑定IP地点和断标语。该函数的第一个参数指定待绑定的Socket描写符;第二个参数指定一个sockaddr布局,该布局是这样界说的:

struct sockaddr {
       u_short sa_family;
       char sa_data[14];
     };

sa_family指定地点族,对付TCP/IP协议族的套接字,给其置AF_INET。当对TCP/IP协议族的套接字举办绑按时,我们凡是利用另一个地点布局:

struct sockaddr_in {
       short  sin_family;
       u_short sin_port;
       struct in_addr sin_addr;
       char  sin_zero[8];
     };

个中sin_family置AF_INET;sin_port指明端标语;sin_addr布局体中只有一个独一的字段s_addr,暗示IP地点,该字段是一个整数,一般用函数inet_addr()把字符串形式的IP地点转换成unsigned long型的整数值后再置给s_addr。有的处事器是多宿主机,至少有两个网卡,那么运行在这样的处事器上的处事措施在为其Socket绑定IP地点时可以把htonl(INADDR_ANY)置给s_addr,这样做的长处是岂论哪个网段上的客户措施都能与该处事措施通信;假如只给运行在多宿主机上的处事措施的Socket绑定一个牢靠的IP地点,那么就只有与该IP地点处于同一个网段上的客户措施才气与该处事措施通信。我们用0来填充sin_zero数组,目标是让sockaddr_in布局的巨细与sockaddr布局的巨细一致。下面是一个bind函数挪用的例子:

#p#副标题#e#
#p#分页标题#e#

 struct sockaddr_in saddr;
   saddr.sin_family = AF_INET;
   saddr.sin_port = htons(8888);
   saddr.sin_addr.s_addr = htonl(INADDR_ANY);
   bind(ListenSocket,(struct sockaddr *)&saddr,sizeof(saddr));

八、listen函数

int listen( SOCKET s, int backlog );

处事措施可以挪用listen函数使其流套接字s处于监听状态。处于监听状态的流套接字s将维护一个客户毗连请求行列,该行列最多容纳backlog个客户毗连请求。如果该函数执行乐成,则返回0;假如执行失败,则返回SOCKET_ERROR。

九、accept函数

 SOCKET accept(
    SOCKET s,
    struct sockaddr FAR *addr, 
    int FAR *addrlen 
   );

处事措施挪用accept函数从处于监听状态的流套接字s的客户毗连请求行列中取出排在最前的一个客户请求,而且建设一个新的套接字来与客户套接字建设毗连通道,假如毗连乐成,就返回新建设的套接字的描写符,今后与客户套接字互换数据的是新建设的套接字;假如失败就返回INVALID_SOCKET。该函数的第一个参数指定处于监听状态的流套接字;操纵系统操作第二个参数来返回新建设的套接字的地点布局;操纵系统操作第三个参数来返回新建设的套接字的地点布局的长度。下面是一个挪用accept的例子:

 struct sockaddr_in ServerSocketAddr;
     int addrlen;
     addrlen=sizeof(ServerSocketAddr);
     ServerSocket=accept(ListenSocket,(struct sockaddr *)&ServerSocketAddr,&addrlen);

十、connect函数

int connect(
    SOCKET s,             
    const struct sockaddr FAR *name, 
    int namelen            
   );

客户措施挪用connect函数来使客户Socket s与监听于name所指定的计较机的特定端口上的处事Socket举办毗连。假如毗连乐成,connect返回0;假如失败则返回SOCKET_ERROR。下面是一个例子:

struct sockaddr_in daddr;
     memset((void *)&daddr,0,sizeof(daddr));
     daddr.sin_family=AF_INET;
     daddr.sin_port=htons(8888);
     daddr.sin_addr.s_addr=inet_addr("133.197.22.4");
     connect(ClientSocket,(struct sockaddr *)&daddr,sizeof(daddr));

 

    关键字:

天才代写-代写联系方式