精华内容
下载资源
问答
  • WinSock

    2014-04-18 17:21:01
    WinSock
  • winsock

    2019-10-10 16:28:15
    加载Winsock库函数 : WSAStartup 1 int WSAStartup( 2 WORD wVersionRequested,//指定想要加载的winsock库 3 LPWSADATA lpWSAData//指向 WSADATA的指针,用来返回DLL库的详细信息 4 ); WSADat头结构 1 ...

    加载Winsock库函数 : WSAStartup

    1 int WSAStartup(
    2                WORD wVersionRequested,//指定想要加载的winsock库
    3                LPWSADATA lpWSAData//指向 WSADATA的指针,用来返回DLL库的详细信息
    4 );

    WSADat头结构

    复制代码

     1 typedef struct WSAData
     2 {
     3     WORD wVersion;    //库文件建议应用程序使用的版本
     4     WORD wHighVersion;    //库文件支持的最高版本
     5     char szDescription[WSADESCRIPTION_LEN+1];    //库描述字符串
     6     char szSystemStatus[WSASYS_STATUS_LEN+1];    //系统状态字符串
     7     unsigned short iMaxSockets;    //同时支持的最大套接字的数量
     8     unsigned short iMaxUdpDg;    //2.0版中已废弃的参数
     9     char FAR* lpVendorInfo;    //已废弃的参数
    10 }WSADATA,FAR* LOWSADATA;

    复制代码

    每一个WSAStart调用必须对应一个队WSAClean的调用,这个函数用来释放winsock库

    int WSACleanup(void);

    如果想使用winsock库,应该包含对应的库文件

    1 #pragma comment(lib,"WS2_32")

    以后封装的经常用到的CInitSock类

    复制代码

     1 #include <winsock2.h>
     2 #pragma comment(lib,"WS2_32")
     3 class CInitSock
     4 {
     5 public:
     6     CInitSock(BYTE minorVer=2,BYTE majorVer=2)
     7     {
     8         WSADATA wsaData;
     9         WORD sockVersion = MAKEWORD(minorVer,majorVer);
    10         if(::WSAStartup(sockVersion,&wsaData)!=0)
    11         {
    12             exit(0);
    13         }
    14     }
    15     ~CInitSock()
    16     {
    17         ::WSACleanup();
    18     }
    19 };
    展开全文
  • Winsock

    千次阅读 2019-07-22 22:13:24
    WinSockWinsock初始化、反初始化错误检查和处理使用IP协议创建基本的Winsock调用来建立通信IPv4寻址字节排序创建套接字面向连接的通信在Winsock中,建立通信的步骤:服务器:客户机:套接字状态 Winsock 编译采用了...

    Winsock

    • 编译采用了WINSOCK.H的应用程序时,需要链接到WS2_32.LIB库
    • 使用WINSOCK.H时,需要链接到WSOCK32.LIB
    • 使用MSWSOCK.H时,需要链接到MSWCOCK.DLL
    初始化、反初始化

    1. 加载Winsock库
    示例:

    	WSADATA wsaData;
    	WSAStartup( MAKEWORD(2, 2), &wsaData);
    

    原型:

    int
    WSAAPI
    WSAStartup(
        __in WORD wVersionRequested,	//用于指定准备加载的Winsock库的版本,高位字节是次版本,低字节是主版本。通常使用MAKEWORD(x,y)来指定【x是高位字节,y是低位字节】
        __out LPWSADATA lpWSAData	//用与其加载的库版本有关的信息填充这个结构
        );
        
    //WSADATA
    typedef struct WSAData {
            WORD                    wVersion;	//设置为将要使用的Winsock版本
            WORD                    wHighVersion;	//包含了现有的Winsock库的最高版本
    #ifdef _WIN64
            unsigned short          iMaxSockets;
            unsigned short          iMaxUdpDg;
            char FAR *              lpVendorInfo;
            char                    szDescription[WSADESCRIPTION_LEN+1];
            char                    szSystemStatus[WSASYS_STATUS_LEN+1];
    #else
            char                    szDescription[WSADESCRIPTION_LEN+1];
            char                    szSystemStatus[WSASYS_STATUS_LEN+1];
            unsigned short          iMaxSockets;	//可以同时打开的最大套接字数量,不固定,尽量不要用这个值
            unsigned short          iMaxUdpDg;	//数据报的最大长度,不固定,尽量不要用这个值
            char FAR *              lpVendorInfo;
    #endif
    } WSADATA, FAR * LPWSADATA;
    

    在这里插入图片描述
    2. 释放
    使用后需要调用WSACleanup函数,来使Winsock释放所有由Winsock分配的资源,并取消这个应用程序挂起的Winsock调用。
    原型:
    int WSAAPI WSACleanup( void );

    错误检查和处理

    出现错误时(比如SOCKET_ERROR),可以调用WSAGetLastError函数来获得一段代码,这段代码专用来说明错误
    原型:

    #if INCL_WINSOCK_API_PROTOTYPES
    WINSOCK_API_LINKAGE
    int
    WSAAPI
    WSAGetLastError(
        void
        );
    #endif /* INCL_WINSOCK_API_PROTOTYPES */
    
    • 如果想要手动设置WSAGetLastError获取的错误代码,可以调用WSASetLastError。
    • 注意:WSAStartup函数的调用不能使用WSAGetLastError来确定导致故障的特定错误(因为Winsock没有加载),用WSAStartup的返回状态判断(0是成功)

    使用IP协议创建基本的Winsock调用来建立通信

    • Winsock是一种独立于协议的接口
    • IP是一种无连接协议,它不能确保数据传输的成功
    • TCP和UDP通过IP进行面向连接和无连接的数据通信
    IPv4寻址

    程序通过sockaddr_in结构来指定IP地址和服务端口信息
    示例:

    	sockaddr_in sockAddr;
    	memset(&sockAddr, 0, sizeof(sockAddr));
    	sockAddr.sin_family = PF_INET;		//#define PF_INET         AF_INET,该字段设为AF_INET,以告知Winsock此时正在使用IP地址族。
    	sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    	sockAddr.sin_port = htons(1234);	//端口号在选择的时候,需要特别注意,某些端口是“已知的”服务保留的
    

    sockaddr_in结构:

    struct sockaddr_in {
            short   sin_family;		//协议族
            u_short sin_port;		//端口号
            struct  in_addr sin_addr;	//ip
            char    sin_zero[8];		//填充项,以使SOCKADDR_IN结构和SOCKADDR结构的长度一样
    };
    

    inet_addr函数可以将一个点分的IP转换成一个32位的无符号长整数。

    字节排序

    网络字节(network-byte)顺序:从最有意义到最无意义的字节排序(big-endian)
    将一个数从主机字节顺序转换成网络字节顺序API(具体用法用到的时候再补充吧):

    htol
    WSAHtol
    htons
    WSAHtons
    
    创建套接字
    SOCKET servSock = socket(AF_INET, SOCK_STREAM, 0);
    

    函数原型:

    #if INCL_WINSOCK_API_PROTOTYPES
    WINSOCK_API_LINKAGE
    __checkReturn
    SOCKET
    WSAAPI
    socket(
        __in int af,			//协议的地址族
        __in int type,		//协议的套接字类型。TCP/IP对应SOCK_STREAM;UDP/IP对应SOCK_DGRAM
        __in int protocol	//用于在给定地址族和套接字类型具有多重入口时,对具体的传送作限定。TCP--IPPROTO_TCP;UDP--IPPROTO_UDP
        );
    #endif /* INCL_WINSOCK_API_PROTOTYPES */
    

    面向连接的通信

    • 在IP中,面向连接的通信是通过TCP/IP协议完成的。
    • TCP提供两个计算机间可靠无误的数据传输。
    在Winsock中,建立通信的步骤:
    服务器:

    1. 用Socket或WSASocker将给定的协议的套接字绑定到它已知的名称上

    bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
    

    函数原型:

    #if INCL_WINSOCK_API_PROTOTYPES
    WINSOCK_API_LINKAGE
    int
    WSAAPI
    bind(
        __in SOCKET s,		//等待客户机连接的套接字
        __in_bcount(namelen) const struct sockaddr FAR * name,	//缓冲区,根据使用的协议,将实际地址填充到一个地址缓冲区,并在调用bind的时候将其转换为一个struct sockaddr
        __in int namelen	//要传递的、由协议决定的地址结构的长度
        );
    #endif /* INCL_WINSOCK_API_PROTOTYPES */
    
    • 一旦出错,bind会返回SOCKET_ERROR。
    • 对于bind而言,最常见的错误是WSAEADDINUSE。
    • 如果使用的是TCP/IP,WSAEADDINUSE表示的是另一个进程已经同本地的IP接口及端口号绑定到了一起,或者那个IP和端口号处于TIME_WAIT状态。
    • 假如对一个已被绑定的套接字调用bind,返回的会是WSAEFAULT错误。

    2. 将套接字置为监听模式
    listen(servSock, 20);
    函数原型:

    #if INCL_WINSOCK_API_PROTOTYPES
    WINSOCK_API_LINKAGE
    int
    WSAAPI
    listen(
        __in SOCKET s,	//被绑定的套接字
        __in int backlog		//指定了被搁置的连接的最大队列长度。
        );
    #endif /* INCL_WINSOCK_API_PROTOTYPES */
    
    • 因为在同一时间,可能会有多个服务器的连接请求,如果请求的数量过backlog,那么前面的backlog个请求被放在一个“挂起”队列中,以便应用程序(服务器)依次为他们提供服务。而backlog之后的连接请求都会失败,错误为WSAECONNREFUSED。
    • 一旦服务器接收了一个连接,那个连接请求就会从队列中删去,以便别人可以继续发出请求。
    • WSAEINVAL通常意味着,在调用listen之前没有调用bind。

    3. 若一台客户机试图创立连接,服务器必须通过accept或WSAAccept调用来接受连接

    	SOCKADDR clntAddr;
    	int nSize = sizeof(SOCKADDR);
    	SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize);
    

    函数原型:

    #if INCL_WINSOCK_API_PROTOTYPES
    WINSOCK_API_LINKAGE
    __checkReturn
    SOCKET		//返回值:一个新的套接字,用于已经被接受的那个客户机的连接。(后续的消息发送什么的应该用这个套接字)
    WSAAPI
    accept(
        __in SOCKET s,	//监听的套接字
        __out_bcount_opt(*addrlen) struct sockaddr FAR * addr,	//新连接的地址信息(输出)
        __inout_opt int FAR * addrlen	//连接结构体的大小
        );
    #endif /* INCL_WINSOCK_API_PROTOTYPES */
    
    • 对于连接成功的客户机,在后续的操作中应该使用accept返回的新的套接字
    • 原本的监听套接字仍然用于接受其他客户机的连接,并且仍处于监听模式
    • WSAAccept可以根据指定条件接受一个连接
    客户机:

    客户机的创建步骤:

    1. 创建一个套接字
    2. 建立一个SOCKADDR地址结构,结构名称为准备连接到的服务器名。(对于TCP/IP,这是客户机应用程序锁监听的服务器的IP地址和端口号)
    3. 用connect或WSAConnect初始化客户机与服务器的连接
    套接字状态

    连接:

    • 对于每个套接字来说,它的初始状态都是CLOSED。
    • 若客户机初始化了一个连接,就会向服务器发送一个SYN包,同时将客户机套接字的状态置为SYN_SENT。
    • 服务器收到SYN包后,会发出一个SYN-ACK包,客户机需要用一个ACK包对它做出响应。此时,客户机的套接字将处于ESTABLISHED状态。
    • 如果服务器一直不发送SYN-ACK包,客户机就会超时,并返回CLOSED状态。
    • 服务器的套接字同本地接口及端口绑定起来,并在它上面进行监听,那么套接字的状态便是LISTEN。
    • 客户机试图与服务器连接时,服务器就会收到一个SYN包,并用一个SYN-ACK包作出回应。此时,服务器套接字的状态就编程SYN_RCVD。
    • 最后,客户机发出一个ACK包,它将使服务器套接字的状态变成ESTABLISHED。

    关闭连接:
    一旦应用程序处于ESTABLISHED状态,就可以通过两种方法来关闭它。
    主动关闭:

    • 应用程序会发出一个FIN包(应用程序调用closesocket或shutdown),并且套接字编程FIN_WAIT_1。
    • 通信的对方会用一个ACK包作为回应,套接字的状态随之编程FIN_WAIT_2
    展开全文
  • WINSOCK

    2007-11-19 10:27:15
    是做好的PPT.简单介绍下WINSOCK.
  • WINSOCK控件

    2019-07-01 11:34:07
    WINSOCK控件的调用实例,方便没有使用过winsock控件的人学习,快速掌握TCP编程
  • 现象: 服务器无法上网,qq安全管家的网络修复卡在dns那里不动,看任务管理器dhcp服务占用很高 cmd ping同局域网地址可以ping通,ping外网不行 使用cmd 输入netsh winsock reset 显示找不到指定文件 解决办法: 怀疑...
  • WINSOCK.rar

    2021-04-09 10:19:29
    VB 通过WINSOCK 连接二维码识别器
  • vb winsock

    2014-07-18 13:58:37
    winsock控件说明,讲述winsock控件的使用注意事项
  • winsock2

    2012-12-26 18:22:03
    winsock2
  • 由于恶意软件、木马病毒攻击造成无法上网的问题,有可能是由于winsock配置错误造成的,这个小工具能够重置并修复Winsock配置到默认或者干净的状态。
  • WinSock Expert

    2018-09-01 16:37:18
    WinSock Expert 是一款由acai制作的抓包工具,WinSock Expert 可用来监视和修改网络发送和接收数据的程序,可以用来帮助您调试网络应用程序,分析网络程序的通信协议(如分析OICQ的发送接收数据),并且在必要的时候...
  • winsock编程

    2015-12-04 19:30:57
    利用winsock api 实现局域网聊天程序 可以看一下 能运行
  • 适用于误删winsockwinsock2注册表文件(win10家庭版)的童鞋 适用于误删winsockwinsock2注册表文件(win10家庭版)的童鞋 适用于误删winsockwinsock2注册表文件(win10家庭版)的童鞋
  • Win10家庭版 误删winsockwinsock2注册表的解决方案

    万次阅读 多人点赞 2017-04-02 16:20:36
    晚上不小心把winsockwinsock2注册表删除了,还没有做备份…简直是作死… 因为这2个注册表被删除,直接导致电脑无法上网,详细原因涉及到TCP/IP网络通信协议,这里不深入。 解决方案主要有2种,一种是手动安装...

    晚上不小心把winsock和winsock2注册表删除了,还没有做备份…简直是作死…
    因为这2个注册表被删除,直接导致电脑无法上网,详细原因涉及到TCP/IP网络通信协议,这里不深入。
    解决方案主要有2种,一种是手动安装TCP/IP协议;另一种就是直接从相同系统的其他电脑上导出一份winsock和winsock2注册表,然后在出问题的电脑上导入,win10家庭版应该只能用这种方式,或者用其他注册表修复软件。
    在第一种方法中,win10家庭版在安装TCP/IP协议时将会被组策略拦截下来,导致无法完成安装,而因为不存在本地组策略编辑器(win10 专业版有),而且这时电脑无法上网,无法进行升级。所以该方法将被锁死。
    因此用到了第二种方法,即导入其他正常电脑上的导出文件,这里提供下win10 家庭版的winsock和winsock2导出文件,方便遇到该问题的童鞋解决
    1.CSDN http://download.csdn.net/detail/yeyinglingfeng/9802170
    2.度盘 http://pan.baidu.com/s/1kUFemI7 (csdn自己给资源加下载分也是醉了,还不能改和删= =,用这个下吧,免费的)
    3.鉴于有童鞋出现解压错误的情况,再给一个解压完的下载地址
    百度云 :https://pan.baidu.com/s/18Jzge52vcRz-iuzNQ0xWVQ 提取码 ywq4
    github : https://github.com/SecondMagic/Team-Report-pic

    说下使用方法吧:
    1.下载上面给出的导出文件
    2.运行regedit,先右键开始,然后点击运行,按住win+R键也行
    右键开始,点击运行

    输入regedit

    3.找到winsock和winsock2,路径如下
    这里写图片描述

    4.删除winsock和winsock2这2个文件
    这里写图片描述

    5.导入下载的2个文件,记住2个都要导入一遍,然后重启电脑就行了,如果还是不行就在命令行(就是第2步改成输入cmd啦,后面步骤不用再做一遍)输入netsh winsock reset运行再重启即可
    这里写图片描述

    这次教训很惨重,你能想象到只有一台电脑,电脑上的itunes也刚被卸掉,手头只有一台iPhone和ipad,方圆几公里没熟人和网吧的痛苦吗?电脑无法上网导致无法下载导出文件,无法下载修复工具,iPhone和ipad下载了无法传给电脑(因为这2个注册表关系到网络协议,所以就算电脑链接到无线,也无法进行无线传输)。我都想买只android系统的手机了,手机里有导出文件却无法传给电脑,简直痛苦…
    劝告大家在对注册表进行编辑的时候一定要做备份。

    展开全文
  • Winsock编程

    2013-07-05 17:59:42
    Winsock编程基于VC6.0
  • 它旨在提供对基本Winsock函数和数据结构的理解,以及它们如何协同工作。 用于说明的客户端和服务器应用程序是一个非常基本的客户端和服务器。 Microsoft Windows软件开发工具包(SDK)附带的示例中包含更高级的代码...

    以下是Windows套接字编程入门的分步指南。 它旨在提供对基本Winsock函数和数据结构的理解,以及它们如何协同工作。

    用于说明的客户端和服务器应用程序是一个非常基本的客户端和服务器。 Microsoft Windows软件开发工具包(SDK)附带的示例中包含更高级的代码示例。

    客户端和服务器应用程序的前几个步骤相同。

    关于服务器和客户端
    创建一个基本的Winsock应用程序
    正在初始化Winsock
    

    以下部分描述了创建Winsock客户端应用程序的其余步骤。

    为客户端创建套接字
    连接到插座
    在客户端上发送和接收数据
    断开客户端连接
    

    以下部分描述了创建Winsock服务器应用程序的其余步骤。

    为服务器创建套接字
    绑定套接字
    听一个插座
    接受连接
    在服务器上接收和发送数据
    断开服务器连接
    

    这些基本示例的完整源代码。

    运行Winsock客户端和服务器代码示例
    完整的Winsock客户端代码
    完整的Winsock服务器代码
    

    高级Winsock实例

    Windows SDK附带了几个更高级的Winsock客户端和服务器示例。 默认情况下,Winsock示例源代码由Windows SDK for Windows 7安装在以下目录中:

    C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\NetDs\winsock

    在早期版本的Windows SDK中,上述路径中的版本号将更改。 例如,Winsock示例源代码由Windows SDK for Windows Vista安装在以下默认目录中

    C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\NetDs\winsock

    以下列出的高级样本按从高到低的顺序排列,可在以下目录中找到:

    iocp
    

    该目录包含三个使用I / O完成端口的示例程序。 这些程序包括一个使用WSAAccept函数的Winsock服务器(iocpserver),一个使用AcceptEx函数的Winsock服务器(iocpserverex),以及一个用于测试这些服务器中的任何一个的简单多线程Winsock客户端(iocpclient)。 服务器程序支持多个客户端通过TCP / IP连接并发送任意大小的数据缓冲区,然后服务器回送给客户端。 为方便起见,开发了一个简单的客户端程序iocpclient,用于连接并不断向服务器发送数据,以便使用多个线程对其进行压力。 使用I / O完成端口的Winsock服务器提供最强大的性能。

    overlap
    

    此目录包含使用重叠I / O的示例服务器程序。 示例程序使用AcceptEx函数和重叠I / O来有效地处理来自客户端的多个异步连接请求。 服务器使用AcceptEx函数在单线程Win32应用程序中复用不同的客户端连接。 使用重叠I / O可实现更高的可伸缩性。

    WSAPoll
    

    该目录包含一个演示WSAPoll函数使用的基本示例程序。 组合的客户端和服务器程序是非阻塞的,并使用WSAPoll函数来确定何时可以无阻塞地发送或接收。 此示例更多用于说明,而不是高性能服务器。‘

    simple
    

    该目录包含三个基本示例程序,用于演示服务器使用多个线程。 这些程序包括一个简单的TCP / UDP服务器(简单),一个仅使用TCP的服务器(simples_ioctl),它使用Win32控制台应用程序中的select函数来支持多个客户端请求,以及一个客户端TCP / UDP程序(simplec),用于测试服务器。 服务器演示了使用多个线程来处理多个客户端请求。 此方法具有可伸缩性问题,因为为每个客户端请求创建了单独的线程。

    accept
    

    该目录包含基本样本服务器和客户端程序。 服务器演示如何使用select函数使用非阻塞接受或使用WSAAsyncSelect函数使用异步接受。 此示例更多用于说明,而不是高性能服务器。’

    一、关于服务器和客户端

    有两种不同类型的套接字网络应用程序:服务器和客户端。

    服务器和客户端有不同的行为; 因此,创建它们的过程是不同的。 以下是创建流式TCP / IP服务器和客户端的一般模型。

    一)、服务器

    初始化Winsock。
    创建一个套接字。
    绑定套接字。
    听取客户端的套接字。
    接受来自客户端的连接。
    接收和发送数据。
    断开链接。
    

    二)、客户端

    初始化Winsock。
    创建一个套接字。
    连接到服务器。
    发送和接收数据。
    断开链接。
    
    
    
    注意
    
    对于客户端和服务器,某些步骤是相同的。 这些步骤几乎完全相同。 本指南中的某些步骤将特定于正在创建的应用程序类型。
    

    二、创建一个基本的Winsock应用程序

    1、为了创建基本的Winsock应用程序

    2、创建一个新的空项目。

    3、将空C ++源文件添加到项目中。

    4、确保构建环境引用Microsoft Windows软件开发工具包(SDK)或早期平台软件开发工具包(SDK)的Include,Lib和Src目录。确保构建环境链接到Winsock库文件Ws2_32.lib。 使用Winsock的应用程序必须与Ws2_32.lib库文件链接。 #pragma注释向链接器指示需要Ws2_32.lib文件。

    5、开始编写Winsock应用程序。 通过包含Winsock 2头文件来使用Winsock API。 Winsock2.h头文件包含大多数Winsock函数,结构和定义。 Ws2tcpip.h头文件包含在针对TCP / IP的WinSock 2协议特定附件文档中引入的定义,其中包括用于检索IP地址的较新功能和结构。

    注意
    
    Stdio.h用于标准输入和输出,特别是printf()函数。
    
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdio.h>
     
    #pragma comment(lib, "Ws2_32.lib")
     
    int main() {
      return 0;
    }
    
    注意
    
    如果应用程序正在使用IP Helper API,则需要Iphlpapi.h头文件。 当需要Iphlpapi.h头文件时,Winsock2.h头文件的#include行应该放在Iphlpapi.h头文件的#include行之前。
    
    Winsock2.h头文件内部包含来自Windows.h头文件的核心元素,因此Winsock应用程序中的Windows.h头文件通常没有#include行。 如果Windows.h头文件需要#include行,则应在#define WIN32_LEAN_AND_MEAN宏之前添加#include行。 由于历史原因,Windows.h标头默认包含Windows套接字1.1的Winsock.h头文件。 Winsock.h头文件中的声明将与Windows Sockets 2.0所需的Winsock2.h头文件中的声明冲突。 WIN32_LEAN_AND_MEAN宏可防止Windows.h标头包含Winsock.h。 示例说明如下所示。
    
    #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
    #endif
     
    #include <windows.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <iphlpapi.h>
    #include <stdio.h>
     
    #pragma comment(lib, "Ws2_32.lib")
     
    int main() {
      return 0;
    }
    

    三、初始化Winsock

    调用Winsock函数的所有进程(应用程序或DLL)必须在进行其他Winsock函数调用之前初始化Windows Sockets DLL的使用。 这也确保系统支持Winsock。

    为了初始化Winsock

    1、创建一个名为wsaData的WSADATA对象。

    WSADATA wsaData;

    2、调用WSAStartup并将其值作为整数返回并检查错误。

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

    调用WSAStartup函数以启动WS2_32.dll的使用。

    WSADATA结构包含有关Windows套接字实现的信息。 WSAStartup的MAKEWORD(2,2)参数在系统上发出对Winsock 2.2版的请求,并将传递的版本设置为调用者可以使用的最高版本的Windows套接字支持。

    四、Winsock客户端应用程序

    以下部分描述了创建Winsock客户端应用程序的其余步骤。 以下是创建流式TCP / IP客户端的一般模型。

    为客户端创建套接字
    连接到插座
    在客户端上发送和接收数据
    断开客户端连接
    

    一)、为客户端创建套接字

    初始化之后,必须实例化SOCKET对象以供客户端使用。

    为了创建套接字

    1、声明包含sockaddr结构的addrinfo对象并初始化这些值。 对于此应用程序,未指定Internet地址系列,以便可以返回IPv6或IPv4地址。 应用程序请求套接字类型为TCP协议的流套接字。

    struct addrinfo *result = NULL,
                    *ptr = NULL,
                    hints;
     
    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    

    2、调用getaddrinfo函数,请求在命令行上传递的服务器名称的IP地址。 客户端将连接到的服务器上的TCP端口在此示例中由DEFAULT_PORT定义为27015。 getaddrinfo函数将其值返回为检查错误的整数。

    #define DEFAULT_PORT "27015"
     
    // Resolve the server address and port
    iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        printf("getaddrinfo failed: %d\n", iResult);
        WSACleanup();
        return 1;
    }
    

    3、创建一个名为ConnectSocket的SOCKET对象。

    SOCKET ConnectSocket = INVALID_SOCKET;

    4、调用套接字函数并将其值返回到ConnectSocket变量。 对于此应用程序,请使用调用getaddrinfo返回的第一个IP地址,该地址与hints参数中指定的地址系列,套接字类型和协议相匹配。 在此示例中,指定了TCP流套接字,其套接字类型为SOCK_STREAM,协议为IPPROTO_TCP。 地址系列未指定(AF_UNSPEC),因此返回的IP地址可以是服务器的IPv6或IPv4地址。

    如果客户端应用程序只想使用IPv6或IPv4进行连接,则需要在hints参数中将地址族设置为IPv6的AF_INET6或IPv4的AF_INET。

    // Attempt to connect to the first address returned by
    // the call to getaddrinfo
    ptr=result;
     
    // Create a SOCKET for connecting to server
    ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
        ptr->ai_protocol);
    

    5、检查错误以确保套接字是有效的套接字。

    if (ConnectSocket == INVALID_SOCKET) {
        printf("Error at socket(): %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }
    

    传递给套接字函数的参数可以针对不同的实现进行更改。

    错误检测是成功的网络代码的关键部分。 如果套接字调用失败,则返回INVALID_SOCKET。 上一代码中的if语句用于捕获创建套接字时可能发生的任何错误。 WSAGetLastError返回与上次发生的错误关联的错误号。

    注意
    
    根据应用,可能需要进行更广泛的错误检查。
    

    WSACleanup用于终止WS2_32 DLL的使用。

    二)、连接到套接字

    要使客户端在网络上进行通信,它必须连接到服务器。‘

    为了链接套接字

    调用connect函数,将创建的套接字和sockaddr结构作为参数传递。

    // Connect to server.
    iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        closesocket(ConnectSocket);
        ConnectSocket = INVALID_SOCKET;
    }
     
    // Should really try the next address returned by getaddrinfo
    // if the connect call failed
    // But for this simple example we just free the resources
    // returned by getaddrinfo and print an error message
     
    freeaddrinfo(result);
     
    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }
    

    ’getaddrinfo函数用于确定sockaddr结构中的值。 在此示例中,getaddrinfo函数返回的第一个IP地址用于指定传递给connect的sockaddr结构。 如果连接调用未能通过第一个IP地址,则尝试从getaddrinfo函数返回的链表中的下一个addrinfo结构。

    sockaddr结构中指定的信息包括:

    客户端将尝试连接的服务器的IP地址。
    客户端将连接到的服务器上的端口号。 当客户端调用getaddrinfo函数时,此端口被指定为端口27015。
    

    三)、在客户端上发送和接收数据

    以下代码演示了建立连接后客户端使用的send和recv函数。

    客户端

    #define DEFAULT_BUFLEN 512
     
    int recvbuflen = DEFAULT_BUFLEN;
     
    char *sendbuf = "this is a test";
    char recvbuf[DEFAULT_BUFLEN];
     
    int iResult;
     
    // Send an initial buffer
    iResult = send(ConnectSocket, sendbuf, (int) strlen(sendbuf), 0);
    if (iResult == SOCKET_ERROR) {
        printf("send failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }
     
    printf("Bytes Sent: %ld\n", iResult);
     
    // shutdown the connection for sending since no more data will be sent
    // the client can still use the ConnectSocket for receiving data
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }
     
    // Receive data until the server 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: %d\n", WSAGetLastError());
    } while (iResult > 0);
    

    send和recv函数分别返回发送或接收的字节数的整数值或错误。 每个函数也采用相同的参数:活动套接字,字符缓冲区,要发送或接收的字节数,以及要使用的任何标志。

    四)、断开客户端连接

    一旦客户端完成发送和接收数据,客户端将断开与服务器的连接并关闭套接字。

    为了断开连接并关闭套接字

    1、当客户端完成向服务器发送数据时,可以调用shutdown函数指定SD_SEND以关闭套接字的发送端。 这允许服务器释放此套接字的一些资源。 客户端应用程序仍然可以在套接字上接收数据。

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

    2、当客户端应用程序完成接收数据时,将调用closesocket函数来关闭套接字。

    使用Windows套接字DLL完成客户端应用程序时,将调用WSACleanup函数以释放资源。

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

    五、Winsock服务器应用程序

    以下部分描述了创建Winsock服务器应用程序的其余步骤。 以下是创建流式TCP / IP服务器的一般模型。

    为服务器创建套接字
    绑定套接字
    听一个插座
    接受连接
    在服务器上接收和发送数据
    断开服务器连接
    

    一)、为服务器创建套接字

    初始化之后,必须实例化SOCKET对象以供服务器使用。

    为服务器创建套接字

    1、getaddrinfo函数用于确定sockaddr结构中的值:

    AF_INET用于指定IPv4地址族。
    SOCK_STREAM用于指定流套接字。
    IPPROTO_TCP用于指定TCP协议。
    AI_PASSIVE标志表示调用者打算在调用bind函数时使用返回的套接字地址结构。 当设置AI_PASSIVE标志并且getaddrinfo函数的nodename参数是NULL指针时,套接字地址结构的IP地址部分对于IPv4地址设置为INADDR_ANY,对于IPv6地址设置为IN6ADDR_ANY_INIT。
    27015是与客户端将连接到的服务器关联的端口号。
    

    addadfo结构由getaddrinfo函数使用。

    #define DEFAULT_PORT "27015"
     
    struct addrinfo *result = NULL, *ptr = NULL, hints;
     
    ZeroMemory(&hints, sizeof (hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;
     
    // Resolve the local address and port to be used by the server
    iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        printf("getaddrinfo failed: %d\n", iResult);
        WSACleanup();
        return 1;
    }
    

    2、为服务器创建一个名为ListenSocket的SOCKET对象以侦听客户端连接。

    SOCKET ListenSocket = INVALID_SOCKET;

    3、调用套接字函数并将其值返回给ListenSocket变量。 对于此服务器应用程序,请使用调用getaddrinfo返回的第一个IP地址,该地址与hints参数中指定的地址系列,套接字类型和协议相匹配。 在此示例中,请求IPv4的TCP流套接字,其地址系列为IPv4,套接字类型为SOCK_STREAM,协议为IPPROTO_TCP。 因此,为ListenSocket请求了一个IPv4地址。

    如果服务器应用程序想要侦听IPv6,则需要在hints参数中将地址族设置为AF_INET6。 如果服务器想要同时侦听IPv6和IPv4,则必须创建两个侦听套接字,一个用于IPv6,另一个用于IPv4。 这两个插座必须由应用程序单独处理。

    Windows Vista及更高版本提供了创建单个IPv6套接字的功能,该套接字处于双堆栈模式以侦听IPv6和IPv4。 有关此功能的更多信息,请参阅双栈套接字。

    // Create a SOCKET for the server to listen for client connections
     
    ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    

    4、检查错误以确保套接字是有效的套接字。

    if (ListenSocket == INVALID_SOCKET) {
        printf("Error at socket(): %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }
    

    二)、绑定套接字

    要使服务器接受客户端连接,必须将其绑定到系统中的网络地址。 以下代码演示了如何将已创建的套接字绑定到IP地址和端口。 客户端应用程序使用IP地址和端口连接到主机网络。

    为了绑定套接字

    sockaddr结构保存有关地址系列,IP地址和端口号的信息。

    调用bind函数,将从getaddrinfo函数返回的创建的socket和sockaddr结构作为参数传递。 检查一般错误。

    // Setup the TCP listening socket
        iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            printf("bind failed with error: %d\n", WSAGetLastError());
            freeaddrinfo(result);
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }
    

    调用bind函数后,不再需要getaddrinfo函数返回的地址信息。 调用freeaddrinfo函数以释放getaddrinfo函数为此地址信息分配的内存。

    freeaddrinfo(result);

    三)、监听套接字

    套接字绑定到系统上的IP地址和端口后,服务器必须侦听该IP地址和端口以获取传入的连接请求。

    为了监听套接字

    调用listen函数,将创建的套接字作为参数传递,并将backlog的值,待接受的挂起队列的最大长度作为接受。 在此示例中,backlog参数设置为SOMAXCONN。 此值是一个特殊常量,它指示Winsock提供程序为此套接字允许队列中最大合理数量的挂起连接。 检查一般错误的返回值。

    if ( listen( ListenSocket, SOMAXCONN ) == SOCKET_ERROR ) {
        printf( "Listen failed with error: %ld\n", WSAGetLastError() );
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    

    四)、接受连接

    一旦套接字正在侦听连接,程序必须处理该套接字上的连接请求。

    为了接受套接字上的连接

    1、创建一个名为ClientSocket的临时SOCKET对象,用于接受来自客户端的连接。

    SOCKET ClientSocket;

    2、通常,服务器应用程序将被设计为侦听来自多个客户端的连接。 对于高性能服务器,通常使用多个线程来处理多个客户端连接。

    使用Winsock有几种不同的编程技术可用于侦听多个客户端连接。 一种编程技术是创建一个连续循环,使用listen函数检查连接请求(请参阅侦听套接字)。 如果发生连接请求,应用程序将调用accept,AcceptEx或WSAAccept函数,并将工作传递给另一个线程来处理请求。 其他几种编程技术也是可能的。

    请注意,此基本示例非常简单,不使用多个线程。 该示例也只是侦听并接受单个连接。

    ClientSocket = INVALID_SOCKET;
     
    // Accept a client socket
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    

    3、当客户端连接被接受时,服务器应用程序通常会将接受的客户端套接字(上面示例代码中的ClientSocket变量)传递给工作线程或I / O完成端口,并继续接受其他连接。 在此基本示例中,服务器继续执行下一步。

    有许多其他编程技术可用于侦听和接受多个连接。 这些包括使用select或WSAPoll函数。 Microsoft Windows软件开发工具包(SDK)附带的Advanced Winsock示例中说明了这些各种编程技术中的一些示例。

    注意
    
    在Unix系统上,服务器的通用编程技术是用于监听连接的应用程序。 当接受连接时,父进程将调用fork函数来创建一个新的子进程来处理客户端连接,从父进程继承套接字。 Windows不支持此编程技术,因为不支持fork函数。 此技术通常也不适用于高性能服务器,因为创建新进程所需的资源远远大于线程所需的资源。
    

    五)、在服务器上接收和发送数据

    以下代码演示了服务器使用的recv和send函数。

    为了在套接字上接收和发送数据

    #define DEFAULT_BUFLEN 512
     
    char recvbuf[DEFAULT_BUFLEN];
    int iResult, iSendResult;
    int recvbuflen = DEFAULT_BUFLEN;
     
    // Receive until the peer shuts down the connection
    do {
     
        iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
        if (iResult > 0) {
            printf("Bytes received: %d\n", iResult);
     
            // Echo the buffer back to the sender
            iSendResult = send(ClientSocket, recvbuf, iResult, 0);
            if (iSendResult == SOCKET_ERROR) {
                printf("send failed: %d\n", WSAGetLastError());
                closesocket(ClientSocket);
                WSACleanup();
                return 1;
            }
            printf("Bytes sent: %d\n", iSendResult);
        } else if (iResult == 0)
            printf("Connection closing...\n");
        else {
            printf("recv failed: %d\n", WSAGetLastError());
            closesocket(ClientSocket);
            WSACleanup();
            return 1;
        }
     
    } while (iResult > 0);
    

    send和recv函数分别返回发送或接收的字节数的整数值或错误。 每个函数也采用相同的参数:活动套接字,字符缓冲区,要发送或接收的字节数,以及要使用的任何标志。

    六)、断开服务器连接

    一旦服务器完成从客户端接收数据并将数据发送回客户端,服务器将断开与客户端的连接并关闭套接字。

    为了断开服务器连接

    1、当服务器完成向客户端发送数据时,可以调用shutdown函数指定SD_SEND以关闭套接字的发送端。 这允许客户端释放此套接字的一些资源。 服务器应用程序仍然可以在套接字上接收数据。

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

    2、当客户端应用程序完成接收数据时,将调用closesocket函数来关闭套接字。

    使用Windows套接字DLL完成客户端应用程序时,将调用WSACleanup函数以释放资源。

    // cleanup
    closesocket(ClientSocket);
    WSACleanup();
     
    return 0;
    

    六、运行Winsock客户端和服务器代码示例

    本节包含TCP / IP客户端和服务器应用程序的完整源代码:

    完整的Winsock客户端代码
    完整的Winsock服务器代码
    

    应在启动客户端应用程序之前启动服务器应用程序。

    要执行服务器,请编译完整的服务器源代码并运行可执行文件。 服务器应用程序侦听TCP端口27015以供客户端连接。 一旦客户端连接,服务器就会从客户端接收数据,并将收到的数据回送(发送)回客户端。 当客户端关闭连接时,服务器会关闭客户端套接字,关闭套接字并退出。

    要执行客户端,请编译完整的客户端源代码并运行可执行文件。 客户端应用程序要求在执行客户端时将运行服务器应用程序的计算机的名称或IP地址作为命令行参数传递。 如果客户端和服务器在示例计算机上执行,则可以按如下方式启动客户端:

    客户端localhost

    客户端尝试在TCP端口27015上连接到服务器。客户端连接后,客户端将数据发送到服务器并接收从服务器发回的任何数据。 然后客户端关闭套接字并退出。

    一)、完整的Winsock客户端代码

    以下是基本Winsock TCP / IP客户端应用程序的完整源代码。

    Winsock客户端源代码

    #define WIN32_LEAN_AND_MEAN
     
    #include <windows.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdlib.h>
    #include <stdio.h>
     
     
    // Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
    #pragma comment (lib, "Ws2_32.lib")
    #pragma comment (lib, "Mswsock.lib")
    #pragma comment (lib, "AdvApi32.lib")
     
     
    #define DEFAULT_BUFLEN 512
    #define DEFAULT_PORT "27015"
     
    int __cdecl main(int argc, char **argv) 
    {
        WSADATA wsaData;
        SOCKET ConnectSocket = INVALID_SOCKET;
        struct addrinfo *result = NULL,
                        *ptr = NULL,
                        hints;
        char *sendbuf = "this is a test";
        char recvbuf[DEFAULT_BUFLEN];
        int iResult;
        int recvbuflen = DEFAULT_BUFLEN;
        
        // Validate the parameters
        if (argc != 2) {
            printf("usage: %s server-name\n", argv[0]);
            return 1;
        }
     
        // Initialize Winsock
        iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
        if (iResult != 0) {
            printf("WSAStartup failed with error: %d\n", iResult);
            return 1;
        }
     
        ZeroMemory( &hints, sizeof(hints) );
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
     
        // Resolve the server address and port
        iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
        if ( iResult != 0 ) {
            printf("getaddrinfo failed with error: %d\n", iResult);
            WSACleanup();
            return 1;
        }
     
        // Attempt to connect to an address until one succeeds
        for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
     
            // Create a SOCKET for connecting to server
            ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
                ptr->ai_protocol);
            if (ConnectSocket == INVALID_SOCKET) {
                printf("socket failed with error: %ld\n", WSAGetLastError());
                WSACleanup();
                return 1;
            }
     
            // Connect to server.
            iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
            if (iResult == SOCKET_ERROR) {
                closesocket(ConnectSocket);
                ConnectSocket = INVALID_SOCKET;
                continue;
            }
            break;
        }
     
        freeaddrinfo(result);
     
        if (ConnectSocket == INVALID_SOCKET) {
            printf("Unable to connect to server!\n");
            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: %ld\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;
    }
    

    二)、完整的Winsock服务器代码

    以下是基本Winsock TCP / IP Server应用程序的完整源代码。

    Winsock服务器源代码

    #undef UNICODE
     
    #define WIN32_LEAN_AND_MEAN
     
    #include <windows.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdlib.h>
    #include <stdio.h>
     
    // Need to link with Ws2_32.lib
    #pragma comment (lib, "Ws2_32.lib")
    // #pragma comment (lib, "Mswsock.lib")
     
    #define DEFAULT_BUFLEN 512
    #define DEFAULT_PORT "27015"
     
    int __cdecl main(void) 
    {
        WSADATA wsaData;
        int iResult;
     
        SOCKET ListenSocket = INVALID_SOCKET;
        SOCKET ClientSocket = INVALID_SOCKET;
     
        struct addrinfo *result = NULL;
        struct addrinfo hints;
     
        int iSendResult;
        char recvbuf[DEFAULT_BUFLEN];
        int recvbuflen = DEFAULT_BUFLEN;
        
        // Initialize Winsock
        iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
        if (iResult != 0) {
            printf("WSAStartup failed with error: %d\n", iResult);
            return 1;
        }
     
        ZeroMemory(&hints, sizeof(hints));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
        hints.ai_flags = AI_PASSIVE;
     
        // Resolve the server address and port
        iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
        if ( iResult != 0 ) {
            printf("getaddrinfo failed with error: %d\n", iResult);
            WSACleanup();
            return 1;
        }
     
        // Create a SOCKET for connecting to server
        ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
        if (ListenSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            freeaddrinfo(result);
            WSACleanup();
            return 1;
        }
     
        // Setup the TCP listening socket
        iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            printf("bind failed with error: %d\n", WSAGetLastError());
            freeaddrinfo(result);
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }
     
        freeaddrinfo(result);
     
        iResult = listen(ListenSocket, SOMAXCONN);
        if (iResult == SOCKET_ERROR) {
            printf("listen failed with error: %d\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }
     
        // Accept a client socket
        ClientSocket = accept(ListenSocket, NULL, NULL);
        if (ClientSocket == INVALID_SOCKET) {
            printf("accept failed with error: %d\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }
     
        // No longer need server socket
        closesocket(ListenSocket);
     
        // Receive until the peer shuts down the connection
        do {
     
            iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
            if (iResult > 0) {
                printf("Bytes received: %d\n", iResult);
     
            // Echo the buffer back to the sender
                iSendResult = send( ClientSocket, recvbuf, iResult, 0 );
                if (iSendResult == SOCKET_ERROR) {
                    printf("send failed with error: %d\n", WSAGetLastError());
                    closesocket(ClientSocket);
                    WSACleanup();
                    return 1;
                }
                printf("Bytes sent: %d\n", iSendResult);
            }
            else if (iResult == 0)
                printf("Connection closing...\n");
            else  {
                printf("recv failed with error: %d\n", WSAGetLastError());
                closesocket(ClientSocket);
                WSACleanup();
                return 1;
            }
     
        } while (iResult > 0);
     
        // shutdown the connection since we're done
        iResult = shutdown(ClientSocket, SD_SEND);
        if (iResult == SOCKET_ERROR) {
            printf("shutdown failed with error: %d\n", WSAGetLastError());
            closesocket(ClientSocket);
            WSACleanup();
            return 1;
        }
     
        // cleanup
        closesocket(ClientSocket);
        WSACleanup();
     
        return 0;
    }
    
    展开全文
  • WinSock1.1和WinSock2.0

    2018-06-28 11:51:00
     Windows提供了Windows Socket API(简称WSA),WinSock,目前有两个版本:WinSock1.1 and WinSock2.0  WinSock1.1 and WinSock2.0两个版本向后兼容:源码和二进制代码。WinSock2.0是对WinSock1.1的扩展(增加了很...
  • Winsock.reg

    2019-12-13 15:18:31
    网络无法访问包Winsock2.2错误的注册表导入配置,导入注册表后就可修复,本文件为win10 专业版注册表信息,实际验证可修复win10 家庭版

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 50,511
精华内容 20,204
关键字:

Winsock