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
是等价的,两者可以互换。
明白了吧 ^_^
浙公网安备 33010602011771号