首页 > 系统相关 >突破编程_C++_网络编程(Windows 套接字(常用数据结构))

突破编程_C++_网络编程(Windows 套接字(常用数据结构))

时间:2024-04-08 16:33:17浏览次数:23  
标签:SOCKET Windows WSK 编程 C++ result 接字 Winsock 函数

1 WSADATA

WSADATA 结构体包含了关于 Winsock 实现的一些详细信息,定义如下:

struct WSAData {  
    WORD wVersion;        // Winsock版本号  
    WORD wHighVersion;    // Winsock动态库支持的最高版本号  
    char szDescription[WSADESCRIPTION_LEN+1]; // Winsock描述  
    char szSystemStatus[WSASYSSTATUS_LEN+1];  // 系统状态  
    unsigned short iMaxSockets;  // 最大并发Socket数  
    unsigned short iMaxUdpDg;    // 最大UDP数据报大小  
    char FAR* lpVendorInfo;      // 供应商信息指针  
};

其中:

  1. wVersion:表示 Winsock 的版本号,它是一个 16 位的值,高字节表示主版本号,低字节表示次版本号。

  2. wHighVersion:表示 Winsock 支持的最高版本号,它也是一个 16 位的值,高字节表示主版本号,低字节表示次版本号。

  3. szDescription:一个以空字符结尾的字符串,描述了 Winsock 实现的详细信息,如 “Winsock 2.0”。

  4. szSystemStatus:一个以空字符结尾的字符串,描述了 Winsock 实现的系统状态,如 “Running”。

  5. iMaxSockets:表示 Winsock 实现允许同时打开的最大套接字数量。

  6. iMaxUdpDg:表示 Winsock 实现允许的最大 UDP 数据报大小(以字节为单位)。

  7. lpVendorInfo:一个指向以空字符结尾的字符串的指针,该字符串包含了与 Winsock 实现相关的供应商特定信息。

要使用 Winsock,首先需要调用 WSAStartup() 函数,该函数会初始化 Winsock 并返回一个 WSADATA 结构体。在使用完 Winsock 后,需要调用 WSACleanup() 函数来释放资源。

以下是一个简单的示例,展示了如何使用 WSAStartup() 和 WSACleanup() 函数:

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

int main() {
    WSADATA wsaData;
    int result;

    // 初始化 Winsock
    result = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (result != 0) {
        printf("WSAStartup failed with error: %d\n", result);
        return 1;
    }

    printf("Winsock initialized successfully!\n");
    printf("Winsock version: %d.%d\n", LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
    printf("Winsock description: %s\n", wsaData.szDescription);
    printf("Winsock system status: %s\n", wsaData.szSystemStatus);
    printf("Maximum sockets: %d\n", wsaData.iMaxSockets);
    printf("Maximum UDP datagram size: %d\n", wsaData.iMaxUdpDg);

    // 使用 Winsock 进行网络通信...

    // 清理 Winsock
    WSACleanup();

    return 0;
}

上面代码的输出为:

Winsock initialized successfully!
Winsock version: 2.2
Winsock description: WinSock 2.0
Winsock system status: Running
Maximum sockets: 0
Maximum UDP datagram size: 0

在这个示例中,我们首先调用 WSAStartup() 函数来初始化 Winsock,并将返回的 WSADATA 结构体打印到控制台。然后,我们可以使用 Winsock 进行网络通信。最后,我们调用 WSACleanup() 函数来释放资源。

2 sockaddr_in

sockaddr_in 是一个用于表示 IPv4 地址的结构体,它属于 Windows 套接字(Winsock)库。该结构体定义如下:

struct sockaddr_in {
    short sin_family;          // 地址族,对于 IPv4 地址,应设置为 AF_INET
    u_short sin_port;          // 端口号,使用网络字节顺序
    struct in_addr sin_addr;   // IPv4 地址,使用网络字节顺序
    char sin_zero[8];          // 未使用,应设置为 0
};

其中:

  1. sin_family:表示地址族,对于 IPv4 地址,应设置为 AF_INET。

  2. sin_port:表示端口号,使用网络字节顺序。可以使用 htons() 函数将主机字节顺序的端口号转换为网络字节顺序。

  3. sin_addr:表示 IPv4 地址,使用网络字节顺序。可以使用 inet_addr() 函数将点分十进制表示的 IP 地址字符串转换为网络字节顺序的二进制表示,或者使用 inet_aton() 函数将点分十进制表示的 IP 地址字符串转换为 in_addr 结构体。

  4. sin_zero:未使用,应设置为 0。

以下是一个简单的示例,展示了如何使用 sockaddr_in 结构体:

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

int main() {
    WSADATA wsaData;
    int result;

    // 初始化 Winsock
    result = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (result != 0) {
        printf("WSAStartup failed with error: %d\n", result);
        return 1;
    }

    // 创建一个 TCP 套接字
    SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == INVALID_SOCKET) {
        printf("socket failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    // 填充 sockaddr_in 结构体
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(80);
    serverAddr.sin_addr.s_addr = inet_addr("192.168.1.1");
    memset(serverAddr.sin_zero, 0, sizeof(serverAddr.sin_zero));

    // 连接到服务器
    result = connect(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    if (result == SOCKET_ERROR) {
        printf("connect failed with error: %d\n", WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        return 1;
    }

    // 使用套接字进行通信...

    // 关闭套接字
    closesocket(sock);

    // 清理 Winsock
    WSACleanup();

    return 0;
}

在这个示例中,我们首先调用 WSAStartup() 函数来初始化 Winsock,并创建一个 TCP 套接字。然后,我们填充 sockaddr_in 结构体,并使用 connect() 函数连接到服务器。最后,我们可以使用套接字进行通信,并在完成后关闭套接字和清理 Winsock。

3 SOCKET

在 Windows 套接字(Winsock)编程中,SOCKET 是一个非常重要的数据类型,它代表了一个网络通信的端点。当应用程序想要进行网络通信(例如发送或接收数据)时,它会创建一个或多个套接字,并使用这些套接字与远程主机或本地服务进行通信。

SOCKET 本质上是一个句柄(handle),它用于在 Winsock API 函数调用中唯一标识一个套接字。这个句柄在内部由 Winsock 提供者管理,用于维护与该套接字关联的所有状态信息和资源。

以下是 SOCKET 类型的定义:

typedef UINT_PTR SOCKET;

其中 UINT_PTR 的定义为:

typedef unsigned __int64 UINT_PTR, *PUINT_PTR;

(1)SOCKET 的创建

在 Windows 中,使用 socket() 函数来创建一个新的套接字。这个函数接受三个参数:地址族(例如 AF_INET 表示 IPv4),套接字类型(例如 SOCK_STREAM 表示 TCP 套接字,SOCK_DGRAM 表示 UDP 套接字),以及协议类型(通常设置为 0,表示使用默认的协议)。成功时,socket() 函数返回一个有效的 SOCKET 句柄;失败时返回 INVALID_SOCKET 并设置相应的错误代码。

(2)SOCKET 的使用

一旦创建了一个 SOCKET,应用程序就可以使用它来执行各种网络操作,如绑定到本地地址和端口、连接到远程主机、发送和接收数据等。这些操作通常通过调用其他 Winsock API 函数来完成,例如 bind()、connect()、send()、recv() 等。每个函数都需要一个有效的 SOCKET 句柄作为参数,以便识别要对哪个套接字执行操作。

(3)SOCKET 的关闭

当应用程序完成网络通信并不再需要某个套接字时,它应该使用 closesocket() 函数来关闭该套接字。这将释放与该套接字关联的所有资源,并允许 Winsock 提供者回收这些资源以供将来使用。忘记关闭不再需要的套接字可能会导致资源泄漏和其他问题。

(4)SOCKET 的状态

SOCKET 本身并不直接包含状态信息;状态信息是由 Winsock 提供者在内部维护的。然而,通过调用某些 Winsock API 函数(如 ioctlsocket()),应用程序可以查询或修改套接字的某些状态标志,例如非阻塞模式、广播模式等。

(5)错误处理

与大多数 Winsock API 函数一样,当使用 SOCKET 进行网络操作时,可能会发生错误。为了处理这些错误,应用程序应该检查每个 Winsock API 调用的返回值,并在必要时调用 WSAGetLastError() 来获取更详细的错误代码和信息。

(6)安全性

在使用 SOCKET 进行网络通信时,安全性是一个重要考虑因素。应用程序应该采取适当的措施来保护数据在传输过程中的机密性、完整性和真实性。这可能包括使用加密套接字层(SSL)或传输层安全性(TLS)来加密通信内容,以及验证远程主机的身份和授权。

(7)示例

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

int main() {
    WSADATA wsaData;
    int result;

    // 初始化 Winsock
    result = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (result != 0) {
        printf("WSAStartup failed with error: %d\n", result);
        return 1;
    }

    // 创建一个 TCP 套接字
    SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == INVALID_SOCKET) {
        printf("socket failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    // 使用套接字进行通信...

    // 关闭套接字
    closesocket(sock);

    // 清理 Winsock
    WSACleanup();

    return 0;
}

在这个示例中,我们首先调用 WSAStartup() 函数来初始化 Winsock,并创建一个 TCP 套接字。然后,我们可以使用套接字进行通信,并在完成后关闭套接字和清理 Winsock。

4 WSK_SOCKET(一般用不到)

WSK_SOCKET 结构体在 Windows 套接字(Winsock)的扩展——Windows 套接字内核(WSK)中是一个核心组件。WSK 是 Windows 平台上的一个高级套接字 API,它允许开发者更紧密地集成到网络堆栈中,并提供比传统 Winsock 更高的性能和灵活性。

WSK_SOCKET 结构体通常用于表示一个 WSK 套接字实例,它封装了与特定套接字关联的状态和操作。虽然 WSK_SOCKET 的具体定义可能因 Windows 版本和具体实现而有所不同,但下面是一个大致的概念性描述:

typedef struct _WSK_SOCKET {  
    // 套接字句柄,用于在调用其他 WSK 函数时标识这个套接字  
    SOCKET SocketHandle;  
  
    // 指向 WSK 套接字的提供商控制块的指针  
    PWSK_PROVIDER_CONTROL_BLOCK ProviderControlBlock;  
  
    // 指向 WSK 套接字的传输控制块的指针  
    PWSK_TRANSPORT_CONTROL_BLOCK TransportControlBlock;  
  
    // 指向 WSK 套接字的扩展控制块的指针(如果有的话)  
    PWSK_EXTENSION_CONTROL_BLOCK ExtensionControlBlock;  
  
    // 套接字的状态信息,如是否绑定、是否连接等  
    ULONG State;  
  
    // 与套接字关联的发送和接收队列  
    WSK_SEND_QUEUE SendQueue;  
    WSK_RECEIVE_QUEUE ReceiveQueue;  
  
    // 其他套接字相关的信息和函数指针,如事件处理程序等  
    // ...  
} WSK_SOCKET, *PWSK_SOCKET;

其中:

  1. SocketHandle:这是套接字的句柄,用于在调用其他 WSK 函数时标识这个套接字。

  2. ProviderControlBlock:指向 WSK 套接字的提供商控制块的指针。这个控制块通常包含与特定 WSK 提供商相关的信息,如提供商的句柄、配置等。

  3. TransportControlBlock:指向 WSK 套接字的传输控制块的指针。这个控制块包含与套接字关联的传输层信息,如 IP 地址、端口号等。

  4. ExtensionControlBlock:如果有的话,这是指向 WSK 套接字的扩展控制块的指针。这个控制块可以用于存储与套接字关联的自定义信息或状态。

  5. State:这个字段包含套接字的状态信息,如是否绑定、是否连接等。它可以帮助开发者了解套接字的当前状态。

  6. SendQueue 和 ReceiveQueue:这些队列用于管理套接字的发送和接收操作。它们可以帮助开发者以高效的方式处理网络数据的发送和接收。

  7. 其他字段:除了上述字段外,WSK_SOCKET 结构体还可能包含其他与套接字相关的信息和函数指针,如事件处理程序等。这些字段的具体内容和用途取决于 WSK 的实现和用途。

需要注意的是,WSK_SOCKET 结构体是一个底层结构,通常只在开发网络驱动程序或高性能网络应用程序时才需要直接操作。对于大多数应用程序来说,使用标准的 Winsock API 就足够了。

标签:SOCKET,Windows,WSK,编程,C++,result,接字,Winsock,函数
From: https://blog.csdn.net/h8062651/article/details/137511593

相关文章

  • 突破编程_C++_网络编程(Windows 套接字(API 接口(1)))
    1初始化与清理1.1WSAStartupWSAStartup函数用于初始化Winsock库,并指定应用程序所需的Winsock版本。它允许应用程序与WinsockDLL(动态链接库)建立联系,并准备Winsock环境以供后续使用。(1)函数原型如下:intWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData......
  • 【每周例题】蓝桥杯 C++ 对称排序
    对称排序题目对称排序 题目分析1.因为数字是对称交换,所以我们只需要判断前n/2项需不需要交换就好了2.这里我采用了升序排序,你们也可以尝试降序排序3.我们只需要排序好后再遍历一下整个数组,找出不符合排序的就输出NO就好了代码#include<iostream>#include<bits/stdc+......
  • Java面象对象编程学习(保姆级教学)
    1、基本数据类型和引用数据类型的区别(用内存的角度):基本数据类型:数据值是存储在自己的空间中特点:赋的值也是真实的值引用数据类型:数据值存储在其他空间中,自己空间存储的是地址值特点:赋的值是地址值★【注意:在静态代码块中,随着类的加载进行,而且只进行一......
  • R语言编程和操作系统交互
    文章目录一、重复和循环1.for循环2.while循环二、条件分支1.if-else2.switch三、创建函数1.不含参数的函数2.含参数的函数四、和操作系统的交互1.计算CPUtime2.历史的存储和读取3.工作目录4.文件处理一、重复和循环1.for循环>x<-numeric(10)#占位符,否则无......
  • Windows下安装配置WinPcap
    winpcap官网:http://www.winpcap.org/1.首先下载安装winpcap.exe,http://www.winpcap.org/install/default.htm目的是安装相关驱动和dll,安装完成之后基于winpcap的应用程序才能够正常运行。2.下载winpcap的开发包,头问文件和库文件:http://www.winpcap.org/devel.htm 解压之后主......
  • Windows下配置使用WinPcap
     0、前提   windows:win7x64   WinPcap版本:4.1.3   WinPcap开发包:4.1.2   目标:在VS2010中配置使用winpcap获取目标计算机中安装的网卡列表 1、下载   http://www.winpcap.org/下载winpcap安装包和开发包安装包安装完毕后,解压开发包到某个......
  • 毕业设计jspm少儿编程教育网站系统
    摘要在国家重视教育影响下,教育部门的密确配合下,对教育进行改革、多样性、质量等等的要求,使教育系统的管理和运营比过去十年前更加理性化。依照这一现实为基础,设计一个快捷而又方便的网上少儿编程教育网站系统是一项十分重要并且有价值的事情。对于传统的少儿编程教育网站......
  • 题目 1035: [编程入门]自定义函数之字符类型统计
    一、题目 题目描述编写一函数,由实参传来一个字符串,统计此字符串中字母、数字、空格和其它字符的个数,在主函数中输入字符串以及输出上述结果。只要结果,别输出什么提示信息。输入格式一行字符串输出格式统计数据,4个数字,空格分开。样例输入!@#$%^QWERT   1234567......
  • 运维系列(创建windows服务,亲测有效):Windows 安装Redis(图文详解)
    Windows安装Redis(图文详解)Windows安装Redis(图文详解)一、Redis是什么数据库?二、安装Redis1、下载地址2、安装过程2.1将下载的压缩包解压到一个文件夹中:2.2打开cmd指令窗口,进入到解压的那个文件夹里:2.3输入redis-serverredis.windows.conf:2.4部署Redis在windows下的......
  • Python 高级编程必会之深浅拷贝
    浅拷贝和深拷贝在Python中各有用武之地,正确的选择取决于具体的应用场景、数据结构的复杂性以及对性能的要求。理解这两种方法的工作原理和差异,是每个Python开发者在进行数据复制操作时必须掌握的基础。 在我们进行Python编程的时候,复制(拷贝)数据结构是一种常见的操作,比如当......