WinSock中一个困扰已久的问题

自从接触WinSock以来也有近两年的时间了,一直以来一直有个问题困扰着我,没得到答案,

今天偶然间得到了答案,大喜过望。与诸位分享一下~

在MSDN中搜索"send"关键字可以跳转到如下的链接:ms-help://MS.MSDNQTR.v90.chs/winsock/winsock/send_2.htm

并在文章的底部附有代码

#include <winsock2.h>
#include <stdio.h>

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 27015

int main() {

    //----------------------
    // Declare and initialize variables.
    int iResult;
    WSADATA wsaData;

    SOCKET ConnectSocket;
    struct sockaddr_in clientService; 

    int recvbuflen = DEFAULT_BUFLEN;
    char *sendbuf = "Client: sending data test";
    char recvbuf[DEFAULT_BUFLEN] = "";

    //----------------------
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != NO_ERROR) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    //----------------------
    // Create a SOCKET for connecting to server
    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ConnectSocket == INVALID_SOCKET) {
        printf("socket failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port of the server to be connected to.
    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
    clientService.sin_port = htons( DEFAULT_PORT );

    //----------------------
    // Connect to server.
    iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
    if (iResult == SOCKET_ERROR) {
        printf( "connect failed with error: %d\n", WSAGetLastError() );
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
  }

    //----------------------
    // Send an initial buffer
    iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send() failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    printf("Bytes Sent: %d\n", iResult);

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // Receive until the peer closes the connection
    do {

        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if ( iResult > 0 )
            printf("Bytes received: %d\n", iResult);
        else if ( iResult == 0 )
            printf("Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());

    } while( iResult > 0 );


    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}

其中,注意红色字体标注的那一段代码,在MSDN中搜索sockaddr_in

会看到如下:

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

而其中,in_addr又是一个结构体,再在MSDN里面搜索in_addr

得到:

typedef struct in_addr
{  
    union 
    {    
        struct 
        {      
            u_char s_b1,s_b2,s_b3,s_b4;    
        }S_un_b;    
        struct 
        {      
            u_short s_w1,s_w2;    
        }S_un_w;    
        u_long S_addr;  
    }S_un;
} IN_ADDR,  *PIN_ADDR,  FAR *LPIN_ADDR;
                                            

其中,在in_addr这个结构体中,并未出现s_addr这个字段,只有大写的S_addr,要写也是写成clientService.sin_addr.S_un.S_addr

而不是写成clientService.sin_addr.s_addr,那么着究竟是为什么呢?

点击s_addr,并按F12,进入s_addr的定义,会看着这样一个头文件inaddr.h

 

/*++

Copyright (c) Microsoft Corporation

Module Name:

    inaddr.h

Environment:

    user mode or kernel mode

--*/

#ifndef s_addr
#pragma once

//
// IPv4 Internet address
// This is an 'on-wire' format structure.
//
typedef struct in_addr {
        union {
                struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;
                struct { USHORT s_w1,s_w2; } S_un_w;
                ULONG S_addr;
        } S_un;
#define s_addr  S_un.S_addr /* can be used for most tcp & ip code */
#define s_host  S_un.S_un_b.s_b2    // host on imp
#define s_net   S_un.S_un_b.s_b1    // network
#define s_imp   S_un.S_un_w.s_w2    // imp
#define s_impno S_un.S_un_b.s_b4    // imp #
#define s_lh    S_un.S_un_b.s_b3    // logical host
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;

#endif

 

会看到有这样一个宏 

#define s_addr  S_un.S_addr /* can be used for most tcp & ip code */

于是,

clientService.sin_addr.s_addr
clientService.sin_addr.S_un.S_addr

是等价的,两者可以互换。

明白了吧 ^_^

posted @ 2013-09-07 03:07  JasonScor  阅读(421)  评论(0)    收藏  举报