网络函数和文件管理函数

网络函数和文件管理函数(简短查阅)

查阅的函数

网络函数:

  • WSAStartup: 初始化 Winsock 库,必须在使用其他 Winsock 函数之前调用。
  • socket: 创建套接字并返回套接字句柄。
  • bind: 将套接字绑定到特定的 IP 地址和端口。
  • listen: 将套接字设置为监听状态,等待新的连接。
  • accept: 接受来自客户端的连接请求,并返回新的套接字句柄。
  • connect: 连接到指定的服务器地址和端口。
  • send: 向套接字发送数据。
  • recv: 从套接字接收数据。
  • closesocket: 关闭套接字句柄。
  • WSACleanup: 清理 Winsock 库,必须在应用程序退出之前调用。

文件系统函数:

  • FindFirstFileExW: 搜索指定目录中的文件和/或子目录。
  • FindNextFileW: 继续搜索指定目录中的文件和/或子目录。
  • FindClose: 关闭 FindFirstFileExW 或 FindNextFileW 检索句柄。
  • GetFileAttributes: 获取指定文件的属性。
  • SetFileAttributes: 设置指定文件的属性。
  • ReadFile: 从指定的文件中读取数据。
  • CreateFileW: 创建、打开或截取指定的文件。
  • SetFilePointer: 设置指定文件的文件指针位置。

其他函数:

  • WinExec: 执行一个程序或命令。
  • GetFileSize: 获取指定文件的长度。
  • ShellExcuteW: 打开或运行一个文件、目录或命令。

参考资料

WSAStartup

参数

  • wVersionRequested: 指向包含要使用的 Winsock 版本号的指针。
  • lpWSAData: 指向用于接收 Winsock 版本信息的指针。

返回值

  • 如果成功,则返回值为 0。
  • 如果失败,则返回值是以下错误值之一:
    • WSANOTINITIALISED: Winsock 尚未初始化。
    • WSAEAFNOSUPPORT: 指定的地址族不受支持。
    • WSAEINVAL: lpVersionRequested 参数无效。

示例

#include <Winsock2.h>

int main() {
  WORD wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;

  int nRet = WSAStartup(wVersionRequested, &wsaData);
  if (nRet != 0) {
    // Winsock 初始化失败
    return 1;
  }

  // ...

  WSACleanup();

  return 0;
}

socket

参数

  • af: 指定地址族(AF_INET、AF_INET6 等)。
  • type: 指定套接字类型(SOCK_STREAM、SOCK_DGRAM 等)。
  • protocol: 指定协议类型(IPPROTO_TCP、IPPROTO_UDP 等)。

返回值

  • 如果成功,则返回值为套接字句柄。
  • 如果失败,则返回值为 INVALID_SOCKET。

示例

#include <Winsock2.h>

int main() {
  WORD wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;

  int nRet = WSAStartup(wVersionRequested, &wsaData);
  if (nRet != 0) {
    // Winsock 初始化失败
    return 1;
  }

  // 创建套接字
  SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock == INVALID_SOCKET) {
    // 创建套接字失败
    return 1;
  }

  // ...

  closesocket(sock);

  WSACleanup();

  return 0;
}

bind

参数

  • s: 套接字句柄。
  • lpsockaddr: 指向包含要绑定的地址信息的指针。
  • len: lpsockaddr 指针指向的地址信息的长度。

返回值

  • 如果成功,则返回值为 0。
  • 如果失败,则返回值是以下错误值之一:
    • WSANOTINITIALISED: Winsock 尚未初始化。
    • WSAEADDRINUSE: 指定的地址已被另一个套接字使用。
    • WSAEADDRNOTAVAIL: 指定的地址不可用。

示例

#include <Winsock2.h>

int main() {
  WORD wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;

  int nRet = WSAStartup(wVersionRequested, &wsaData);
  if (nRet != 0) {
    // Winsock 初始化失败
    return 1;
  }

  // 创建套接字
  SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock == INVALID_SOCKET) {
    // 创建套接字失败
    return 1;
  }

  // 绑定套接字
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(8080);
  addr.sin_addr.s_addr = INADDR_ANY;
  int nRet = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
  if (nRet != 0) {
    // 绑定套接字失败
    return 1;
  }

  // ...

  closesocket(sock);

listen

参数

  • s: 套接字句柄。
  • backlog: 侦听队列的最大长度。

返回值

  • 如果成功,则返回值为 0。
  • 如果失败,则返回值是以下错误值之一:
    • WSANOTINITIALISED: Winsock 尚未初始化。
    • WSAEADDRINUSE: 指定的地址已被另一个套接字使用。
    • WSAEADDRNOTAVAIL: 指定的地址不可用。

示例

#include <Winsock2.h>

int main() {
  WORD wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;

  int nRet = WSAStartup(wVersionRequested, &wsaData);
  if (nRet != 0) {
    // Winsock 初始化失败
    return 1;
  }

  // 创建套接字
  SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock == INVALID_SOCKET) {
    // 创建套接字失败
    return 1;
  }

  // 绑定套接字
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(8080);
  addr.sin_addr.s_addr = INADDR_ANY;
  int nRet = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
  if (nRet != 0) {
    // 绑定套接字失败
    return 1;
  }

  // 监听套接字
  int nRet = listen(sock, SOMAXCONN);
  if (nRet != 0) {
    // 监听套接字失败
    return 1;
  }

  // ...

  closesocket(sock);

  WSACleanup();

  return 0;
}

accept

参数

  • s: 套接字句柄。
  • lpsockaddr: 指向接收到连接请求的地址信息的指针。
  • lpaddrlen: lpsockaddr 指针指向的地址信息的长度。

返回值

  • 如果成功,则返回值为新的套接字句柄。
  • 如果失败,则返回值为 INVALID_SOCKET。

示例

#include <Winsock2.h>

int main() {
  WORD wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;

  int nRet = WSAStartup(wVersionRequested, &wsaData);
  if (nRet != 0) {
    // Winsock 初始化失败
    return 1;
  }

  // 创建套接字
  SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock == INVALID_SOCKET) {
    // 创建套接字失败
    return 1;
  }

  // 绑定套接字
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(8080);
  addr.sin_addr.s_addr = INADDR_ANY;
  int nRet = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
  if (nRet != 0) {
    // 绑定套接字失败
    return 1;
  }

  // 监听套接字
  int nRet = listen(sock, SOMAXCONN);
  if (nRet != 0) {
    // 监听套接字失败
    return 1;
  }

  // 接受连接
  SOCKET client = accept(sock, NULL, NULL);
  if (client == INVALID_SOCKET) {
    // 接受连接失败
    return 1;
  }

  // ...

  closesocket(sock);
  closesocket(client);

  WSACleanup();

  return 0;
}

connect

参数

  • s: 套接字句柄。
  • lpsockaddr: 指向要连接的地址信息的指针。
  • lpaddrlen: lpsockaddr 指针指向的地址信息的长度。

返回值

  • 如果成功,则返回值为 0。
  • 如果失败,则返回值是以下错误值之一:
    • WSANOTINITIALISED: Winsock 尚未初始化。
    • WSAEADDRINUSE: 指定的地址已被另一个套接字使用。
    • WSAEADDRNOTAVAIL: 指定的地址不可用。
    • WSAECONNREFUSED: 连接被拒绝。

示例

#include <Winsock2.h>

int main() {
  WORD wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;

  int nRet = WSAStartup(wVersionRequested, &wsaData);
  if (nRet != 0) {
    // Winsock 初始化失败
    return 1;
  }

  // 创建套接字
  SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock == INVALID_SOCKET) {
    // 创建套接字失败
    return 1;
  }

  // 连接到服务器
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(8080);
  addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  int nRet = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
  if (nRet != 0) {
    // 连接失败
    return 1;
  }

  // ...

  closesocket(sock);

  WSACleanup();

  return 0;
}

send

参数

  • s: 套接字句柄。
  • lpBuffer: 要发送的数据的指针。
  • nNumberOfBytesToSend: 要发送的数据的长度。
  • lpNumberOfBytesSent: 指向实际发送的数据长度的指针。

返回值

  • 如果成功,则返回值为实际发送的数据长度。
  • 如果失败,则返回值为 SOCKET_ERROR。

示例

#include <Winsock2.h>

int main() {
  WORD wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;

  int nRet = WSAStartup(wVersionRequested, &wsaData);
  if (nRet != 0) {
    // Winsock 初始化失败
    return 1;
  }

  // 创建套接字
  SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock == INVALID_SOCKET) {
    // 创建套接字失败
    return 1;
  }

  // 连接到服务器
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(8080);
  addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  int nRet = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
  if (nRet != 0) {
    // 连接失败
    return 1;
  }

  // 发送数据
  char buf[] = "Hello, world!";
  int nBytesSent = send(sock, buf, strlen(buf), 0);
  if (nBytesSent == SOCKET_ERROR) {
    // 发送数据失败
    return 1;
  }

  // ...

  closesocket(sock);

  WSACleanup();

  return 0;
}

recv

参数

  • s: 套接字句柄。
  • lpBuffer: 用于接收数据的缓冲区指针。
  • nNumberOfBytesToReceive: 要接收的数据的长度。
  • lpNumberOfBytesReceived: 指向实际接收的数据长度的指针。
  • lpFlags: 指向可选的标志的指针。

返回值

  • 如果成功,则返回值为实际接收的数据长度。
  • 如果失败,则返回值为 SOCKET_ERROR。

示例

#include <Winsock2.h>

int main() {
  WORD wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;

  int nRet = WSAStartup(wVersionRequested, &wsaData);
  if (nRet != 0) {
    // Winsock 初始化失败
    return 1;
  }

  // 创建套接字
  SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock == INVALID_SOCKET) {
    // 创建套接字失败
    return 1;
  }

  // 连接到服务器
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(8080);
  addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  int nRet = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
  if (nRet != 0) {
    // 连接失败
    return 1;
  }

  // 接收数据
  char buf[1024];
  int nBytesReceived = recv(sock, buf, sizeof(buf), 0);
  if (nBytesReceived == SOCKET_ERROR) {
    // 接收数据失败
    return 1;
  }

  // ...

  closesocket(sock);

  WSACleanup();

  return 0;
}

closesocket

参数

  • s: 要关闭的套接字句柄。

返回值

  • 无返回值。

示例

#include <Winsock2.h>

int main() {
  WORD wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;

  int nRet = WSAStartup(wVersionRequested, &wsaData);
  if (nRet != 0) {
    // Winsock 初始化失败
    return 1;
  }

  // ...

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

  // 清理 Winsock
  WSACleanup();

  return 0;
}

WSACleanup

参数

  • 无参数。

返回值

  • 无返回值。

示例

#include <Winsock2.h>

int main() {
  WORD wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;

  int nRet = WSAStartup(wVersionRequested, &wsaData);
  if (nRet != 0) {
    // Winsock 初始化失败
    return 1;
  }

  // ...

  // 清理 Winsock
  WSACleanup();

  return 0;
}

FindFirstFileExW

参数

  • lpFileName: 指向包含要搜索的文件名的字符串的指针。
  • dwFlags: 指定搜索选项。
  • lpFindFileData: 指向用于接收搜索结果的结构的指针。
  • lpFileSize: 指向用于接收文件大小的指针。

返回值

  • 如果成功,则返回值为搜索句柄。
  • 如果失败,则返回值为 INVALID_HANDLE_VALUE。

示例

#include <Windows.h>

int main() {
  HANDLE hFind;
  WIN32_FIND_DATAW fd;

  hFind = FindFirstFileExW(L"C:\\Windows\\*.exe",
                            FindExInfoBasic,
                            &fd,
                            FIND_FIRST_EX_LARGE_FETCH,
                            NULL,
                            NULL);
  if (hFind == INVALID_HANDLE_VALUE) {
    // 搜索失败
    return 1;
  }

  // 显示搜索结果
  do {
    printf("%s (%d)\n", fd.cFileName, fd.nFileSizeHigh);
  } while (FindNextFileW(hFind, &fd));

  FindClose(hFind);

  return 0;
}

FindNextFileW

参数

  • hFind: 搜索句柄。
  • lpFindFileData: 指向用于接收搜索结果的结构的指针。

返回值

  • 如果成功,则返回值为 TRUE。
  • 如果失败,则返回值为 FALSE。

示例

#include <Windows.h>

int main() {
  HANDLE hFind;
  WIN32_FIND_DATAW fd;

  hFind = FindFirstFileExW(L"C:\\Windows\\*.exe",
                            FindExInfoBasic,
                            &fd,
                            FIND_FIRST_EX_LARGE_FETCH,
                            NULL,
                            NULL);
  if (hFind == INVALID_HANDLE_VALUE) {
    // 搜索失败
    return 1;
  }

  // 显示搜索结果
  do {
    printf("%s (%d)\n", fd.cFileName, fd.nFileSizeHigh);
  } while (FindNextFileW(hFind, &fd));

  FindClose(hFind);

  return 0;
}

FindClose

参数

  • hFind: 搜索句柄。

返回值

  • 无返回值。

示例

#include <Windows.h>

int main() {
  HANDLE hFind;
  WIN32_FIND_DATAW fd;

  hFind = FindFirstFileExW(L"C:\\Windows\\*.exe",
                            FindExInfoBasic,
                            &fd,
                            FIND_FIRST_EX_LARGE_FETCH,
                            NULL,
                            NULL);
  if (hFind == INVALID_HANDLE_VALUE) {
    // 搜索失败
    return 1;
  }

  // 显示搜索结果
  do {
    printf("%s (%d)\n", fd.cFileName, fd.nFileSizeHigh);
  } while (FindNextFileW(hFind, &fd));

  // 关闭搜索句柄
  FindClose(hFind);

  return 0;
}

GetFileAttributes

参数

  • lpFileName: 指向包含要获取属性的文件名的字符串的指针。

返回值

  • 如果成功,则返回值为文件属性。
  • 如果失败,则返回值为 INVALID_FILE_ATTRIBUTES。

示例
#include <Windows.h>

int main() {
  DWORD dwAttributes;

  dwAttributes = GetFileAttributes(L"C:\\Windows\\System32\\notepad.exe");
  if (dwAttributes == INVALID_FILE_ATTRIBUTES) {
    // 文件不存在
    return 1;
  }

  // 显示文件属性
  printf("文件属性:%x\n", dwAttributes);

  return 0;
}

SetFileAttributes

参数

  • lpFileName: 指向包含要设置属性的文件名的字符串的指针。
  • dwFileAttributes: 要设置的文件属性。

返回值

  • 如果成功,则返回值为 0。
  • 如果失败,则返回值为 GetLastError() 的值。

示例

#include <Windows.h>

int main() {
  DWORD dwAttributes;

  dwAttributes = GetFileAttributes(L"C:\\Windows\\System32\\notepad.exe");
  if (dwAttributes == INVALID_FILE_ATTRIBUTES) {
    // 文件不存在
    return 1;
  }

  // 将文件属性设置为只读
  SetFileAttributes(L"C:\\Windows\\System32\\notepad.exe", dwAttributes & ~FILE_ATTRIBUTE_WRITE);

  return 0;
}

ReadFile

参数

  • hFile: 要读取的文件句柄。
  • lpBuffer: 用于接收读取数据的缓冲区指针。
  • nNumberOfBytesToRead: 要读取的数据的长度。
  • lpNumberOfBytesRead: 指向实际读取的数据长度的指针。
  • lpOverlapped: 指向重叠结构的指针。

返回值

  • 如果成功,则返回值为 0。
  • 如果失败,则返回值为 GetLastError() 的值。

示例

#include <Windows.h>

int main() {
  HANDLE hFile;
  char buf[1024];

  hFile = CreateFileW(L"C:\\Windows\\System32\\notepad.exe",
                       GENERIC_READ,
                       0,
                       NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);
  if (hFile == INVALID_HANDLE_VALUE) {
    // 打开文件失败
    return 1;
  }

  // 读取文件
  DWORD nBytesRead;
  ReadFile(hFile, buf, sizeof(buf), &nBytesRead, NULL);
  if (nBytesRead == 0) {
    // 文件结束
  } else if (nBytesRead == INVALID_FILE_SIZE) {
    // 文件读取失败
  } else {
    // 显示读取的数据
    printf("%s", buf);
  }

  CloseHandle(hFile);

  return 0;
}

CreateFileW

参数

  • lpFileName: 指向包含要创建或打开的文件名的字符串的指针。
  • dwDesiredAccess: 指示对文件的访问权限。
  • dwShareMode: 指示对文件的共享模式。
  • lpSecurityAttributes: 指向安全描述符的指针。
  • dwCreationDisposition: 指示文件创建方式。
  • dwFlagsAndAttributes: 指示文件属性。
  • lphTemplateFile: 指向模板文件句柄的指针。

返回值

  • 如果成功,则返回值为文件句柄。
  • 如果失败,则返回值为 INVALID_HANDLE_VALUE。

示例

#include <Windows.h>

int main() {
  HANDLE hFile;

  hFile = CreateFileW(L"C:\\test.txt",
                       GENERIC_WRITE,
                       0,
                       NULL,
                       CREATE_NEW,
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);
  if (hFile == INVALID_HANDLE_VALUE) {
    // 创建文件失败
    return 1;
  }

  // 写入文件
  WriteFile(hFile, "Hello, world!", strlen("Hello, world!"), NULL, NULL);

  CloseHandle(hFile);

  return 0;
}

SetFilePointer

参数

  • hFile: 要设置文件指针的文件句柄。
  • lDistanceToMove: 要移动的文件指针的距离。该值可以是正数或负数,表示要移动的字节数。
  • dwMoveMethod: 指定文件指针的移动方式。
  • lpDistanceToMoveHigh: 指向高位文件指针距离的指针。该参数仅在 dwMoveMethod 参数的值为 FILE_BEGINFILE_CURRENT 时有效。

返回值

  • 如果成功,则返回值为新文件指针的位置。
  • 如果失败,则返回值为 INVALID_SET_FILE_POINTER

示例

#include <Windows.h>

int main() {
  HANDLE hFile;
  DWORD dwPos;

  hFile = CreateFileW(L"C:\\test.txt",
                       GENERIC_READ | GENERIC_WRITE,
                       0,
                       NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);
  if (hFile == INVALID_HANDLE_VALUE) {
    // 打开文件失败
    return 1;
  }

  // 将文件指针移动到文件的开始位置
  dwPos = SetFilePointer(hFile, 0, FILE_BEGIN, NULL);
  if (dwPos == INVALID_SET_FILE_POINTER) {
    // 移动文件指针失败
    return 1;
  }

  // 显示文件指针的位置
  printf("文件指针位置:%d\n", dwPos);

  CloseHandle(hFile);

  return 0;
}

WinExec

参数

  • lpCmdLine: 指向包含要执行的命令行的字符串的指针。
  • nCmdShow: 指定窗口的显示方式。

返回值

  • 如果成功,则返回值为命令的退出代码。
  • 如果失败,则返回值为 0。

示例

#include <Windows.h>

int main() {
  // 执行记事本
  int nRet = WinExec(L"notepad.exe", SW_SHOWDEFAULT);
  if (nRet == 0) {
    // 执行失败
    return 1;
  }

  // 等待记事本关闭
  WaitForSingleObject(hProcess, INFINITE);

  return 0;
}

GetFileSize

参数

  • hFile: 要获取文件大小的文件句柄。
  • lpFileSizeHigh: 指向高位文件大小的指针。

返回值

  • 如果成功,则返回值为文件大小。
  • 如果失败,则返回值为 INVALID_FILE_SIZE。

示例

#include <Windows.h>

int main() {
  HANDLE hFile;
  DWORD dwFileSizeLow;
  DWORD dwFileSizeHigh;

  hFile = CreateFileW(L"C:\\Windows\\System32\\notepad.exe",
                       GENERIC_READ,
                       0,
                       NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);
  if (hFile == INVALID_HANDLE_VALUE) {
    // 打开文件失败
    return 1;
  }

  // 获取文件大小
  dwFileSizeLow = GetFileSize(hFile, &dwFileSizeHigh);
  if (dwFileSizeLow == INVALID_FILE_SIZE) {
    // 获取文件大小失败
    return 1;
  }

  // 显示文件大小
  printf("文件大小:%d 字节\n", dwFileSizeLow);

  CloseHandle(hFile);

  return 0;
}

ShellExecuteW

参数

  • lpVerb: 指向包含要执行的操作的字符串的指针。
  • lpFile: 指向包含要执行的文件名的字符串的指针。
  • lpParameters: 指向包含要传递给操作的参数的字符串的指针。
  • lpDirectory: 指向包含要执行操作的目录的字符串的指针。
  • nShow: 指定窗口的显示方式。
  • lpProcessInformation: 指向进程信息结构的指针。

返回值

  • 如果成功,则返回值为 TRUE。
  • 如果失败,则返回值为 FALSE。

示例

#include <Windows.h>

int main() {
  // 在当前目录下执行记事本
  BOOL bRet = ShellExecuteW(NULL, L"open", L"notepad.exe", NULL, NULL, SW_SHOWDEFAULT);
  if (!bRet) {
    // 执行失败
    return 1;
  }

  return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Back~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值