• 2006-11-24

    第7章 Winsock基础 - [winsock]

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://xingzhesun.blogbus.com/logs/3894906.html

    第7章 Winsock基础
    7.1Winsock的初始化
    int WSAStartup(WORD wVersionRequested, LPWSASATA lpWSData);
    7.2错误检查和控制
    int WSAGetLastError(void);
    7.3面向连接的协议
    7.3.1服务器API函数
    1.bind 将指定的套接字同一个已经知道的地址绑定在一起。
    2.listen(SOCKET s, int backlog);
    3.accept和WSAAccept(SOCKET s, struct socket FAR*addr, int FAR* addrlen);
    addr 返回客户机的ip地址信息
    accept返回一个新的套接字,它对应于已经接受的那个客户机连接,对于该客户机后续的所有操作,都使用这个新套接字。
    原来的套接字仍然用于接受客户机连接而处于监听模式。

    int CALLBACK ConditionFunc(
    LPWSABUF lpCallerId,
    LPWSABUF lpCallerData,
    LPQQS lpSOOS,
    LPQOS lpGOOS,
    LPWSABUF lpCalleeId,
    LPWSABUF lpCalleeData,
    GROUP FAR*g,
    DWORD dwCallbackData);

    lpCallerId: 指定建立连接的协议 包含建立连接的那个客户机的IP地址。
    lpCallerData:包含了随连接一道,由客户机发出的任何连接数据。
    lpSQOS,lpGQOS:对客户机请求的任何一个服务质量参数进行指定。
    lpCalleeId:结构中包含与客户机需要与之连接的本地地址。
    服务器将传递给条件的参数处理完之后,必须指出CF_ACCEPT, CF_REJECT , CF_DEFER.

    7.3.2客户机API函数
    1)创建套接字
    2)解析服务器名字(以基层协议为准)
    3)connect WSAConnect初始化一个链接

    TCP状态
    每个套接字的初始化都是closed,如果客户机初始化一个链接就会向服务器发送一个SYN包,同时将客户机的套接字状态设置为SYN_SENT。服务器收到SYNB包后,就会发送一个SYN-ACK包
    。作为客户机,需要一个ACK包对它作出反应。此时客户机的套接字就会变成ESTABLISHED状态。如果服务器一直不发送SYN-ACK包,客户机就会超时并返回CLOSED状态。

    若一个服务器套接字同一个本地接口和端口绑定起来,并在上面监听,那么套接字的状态是LISTEN。客户机试图与之连接时,服务器会收到一个SYN包,并用一个SYN-ACK包做出相应。服务器套接字
    变成SYN-RCVD,最后客户机一个ACK包,令服务器套接字变成ESTABLISHED状态。

    主动关闭套接字closesocket,shutdown时会向对方发送一个FIN包,而且套接字的专题变为FIN-WAIT-1。正常情况下通信对方会回应一个ACK包,套接字的状态变成FIN-WAIT-2。如果对方也关闭了连接,便会发出一个FIN包。我的机器则会相应一个ACK包,并将已方套接字的状态至为TIME-WAIT。
    7.3.3数据传输
    所有关系到收发数据的缓冲都属于简单哦案的char类型。WideCharToMultiByte
    int send(SOCKET S,
    const char FAR* buf,
    int len,
    int flags);
    带外数据:对已经建立链接的流套接字上的应用来说,如果需要发送的数据比流上的普通数据重要得多,便可将这些重要的数据标记为到外数据out-of-band OOB.位于连接另一端的应用可通过一个独立的逻辑信道来接收和处理OOB数据。
    int recv(SOCKET s, char FAR* buf, int len, int flags);

    7.3.4流协议
    大多面向连接的协议同时也是流式传输协议。不能保证对请求的数据量进行读取或者写入。也就是当send recv时不能保证数据的全部发送和接收。

    char sendbuff[2048];
    int nBytes = 2048;
    int nLeft;
    int idx;

    nLeft = nBytes;
    idx = 0;
    while(nLeft>0)
    {
    ret = send(s, &sendbuff[idx], nLeft,0);
    if(ret==SOCKET_ERROR)
    {
    //ERROR
    }
    nLeft -= ret;
    idx += ret;
    }
    7.3.5中断连接
    1.shutdown(SOCKET s, int how); SD_REVEIVE SD_SEND SD_BOTH 表示不再接收,发送和收发。
    2.closesocket(SOCKET s); 释放套接字描述符相关联的资源,包括丢弃所有等候处理的数据。

    7.4无连接协议
    7.4.1接收端
    int recvfrom(SOCKET S, char FAR* buf, int len, int flags, struct socketaddr FAR* from, int FAR* fromlen);
    7.4.2发送端
    int sendto(SOCKET s, const char FAR* buf, int len, int flags, const struct socketaddr FAR* to, int tolen);

    7.4.3基于消息的协议
    面向连接的协议同时也是流式协议,无连接协议几乎都是基于消息的。

    7.5其它API函数
    1.getpeername() 用于获得通信方的套接字地址信息。
    2.getsockname()返回的是指定套接字的本地接口的地址信息。

    7.6Windows CE


    收藏到:Del.icio.us