socket 编程入门教程(二)win32下使用socket:1、WinSock介绍与使用

学习socket最好能有两台以上联网的电脑,以及能获得公网IP的网络接入方式。两年前,我主要使用的是一台win2k3和Debain Linux双系统的电脑,例外有台99年的老机器装着win98,而且没有装VC,测试相当的麻烦。现在买了笔记本,使用的是Vista的win32环境(32位),可以直接和老电脑的Linux联网进行测试。另外,网络环境也换成了电信的ADSL,贵了很多,为的就是能有一个公网IP。接下来的教程我会兼顾winsock的代码,这主要是因为winsock本身对socket几乎是兼容的。所以,这里有必要先说明在VC环境中使用socket的一些简单设置,以及与Linux环境下的细微差别。
我的VC环境依然是2008 Express,在写这篇教程的时候,微软已经发布了VC 2010,目前在微软的官方主页,提供了VC 2010的下载,同时保留着VC 2008的下载。
我们在VC中建立一个控制台的空项目:



我们着手构建自己的第一个winsock程序。
首先win32下与Linux下的socket API需要包含不同的头文件。
在Linux下是这些:

#include <unistd.h>
#include 
<sys/socket.h>
#include 
<arpa/inet.h>

win32下的winsock有多个版本,我所找到的资料中,老的版本是:

#include <winsock.h>

与之对应的需要的链接库为:



这可能可以兼容非常古老的版本中的winsock,比如win98,而微软官方所推荐的是:

#include <winsock2.h>

链接库是:ws2_32.lib,这样就可以使用高版本的winsock。
那么,什么是winsock的版本?这就涉及到winsock的初始化函数WSAStartup:
http://msdn.microsoft.com/en-us/library/ms742213(v=VS.85).aspx
上面是微软的官方说明,我这里构建一个简单的类,希望每次使用的时候引入一个类对象就可以了。

class WinsockAPI{
private:
    WSADATA wsaData;
public:
    WinsockAPI(
int low_byte = 2int high_byte = 2);
    
~WinsockAPI();
    
void showVersion() const;
};

WSADATA是记录着winsock信息的结构。

//class WinsockAPI

WinsockAPI::WinsockAPI(
int low_byte, int high_byte)
{
    
const WORD wVersionRequested = MAKEWORD(low_byte, high_byte);
    
int wsa_startup_err = WSAStartup(wVersionRequested, &wsaData);
    
if (wsa_startup_err != 0) {
        std::cerr 
<< "WSAStartup() failed." << std::endl;
        
throw wsa_startup_err;
    }
}

WinsockAPI::
~WinsockAPI()
{
    WSACleanup();
}

void WinsockAPI::showVersion() const
{
    std::cout    
<< "The version of Winsock.dll is " 
                
<< int(LOBYTE(wsaData.wVersion)) 
                
<< "." 
                
<< int(HIBYTE(wsaData.wVersion)) 
                
<< "." 
                
<< std::endl;
    
return;
}

首先,宏MAKEWORD()将两个int转换为winsock形式的版本号,我这里默认是是2.2,就只需要MAKEWORD(2, 2),如果是老版本的,最低应该是1.0。WSAStartup()将winsock的初始化信息写入一个WSADATA结构(我们这里的wsaData),如果成功返回0,失败将返回一个int的错误代码。这个错误代码直接表示了错误信息,微软官方建议不使用winsock的通用异常信息获取函数WSAGetLastError()获取WSAStartup()的错误信息,这可能是因为如果WSAStartup()失败,那么winsock的错误信息不一定能够正确的构建出来的缘故。
最后,winsock结束后用WSACleanup()清理。
因为socket本身的复杂性,异常信息提示非常重要。WSAGetLastError()的官方说明如下:
http://msdn.microsoft.com/en-us/library/ms741580(VS.85).aspx
错误代码所反馈的信息查询在这里:
http://msdn.microsoft.com/en-us/library/ms740668(v=VS.85).aspx
最后,需要注意的问题是,因为socket是构建在UNIX系统下的(BSD socket是当今所有socket的基础),所以socket很好的利用了UNIX体系“一切都是文件”的性质,每个socket本身也就是一个UNIX文件描述符,因此,Linux下的socket是用关闭文件的函数close()关闭的。但是win32下没这个性质,所以winsock是另外一种抽象,但是好在同样用int作为描述符,关闭需要专门为winsock定做的函数closesocket()。
下篇文章重写了TCP Server的代码(类的抽象和构造也重新写了,将在下一章解释),作为winsock使用的演示。


转载于:https://my.oschina.net/GeorgeSu/blog/264186

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值