Windows 上的网络通信编程

这篇具有很好参考价值的文章主要介绍了Windows 上的网络通信编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 关于 Servers 和 Clients

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

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

1.1 Server

  1. Initialize Winsock.

  2. Create a socket.

  3. Bind the socket.

  4. Listen on the socket for a client.

  5. Accept a connection from a client.

  6. Receive and send data.

  7. Disconnect.

1.2 Client

  1. Initialize Winsock.

  2. Create a socket.

  3. Connect to the server.

  4. Send and receive data.

  5. Disconnect.

2. Create a Basic Winsock Application

创建一个基本的 Winsock 应用需要基于以下条件:

  1. 确保编译环境可以引用 SDK 的 include,Lib 和 Src 目录。

  2. 确保编译环境可以链接到 Winsock 库文件(Ws2_32.lib)。可以通过 #pragma comment(lib, “ws2_32.lib”) 显式的链接。

  3. 编程开始前,使用 Winsock API 要包含 Winsock2.h 头文件,它包含了常用的 Winsock 的函数,结构体和定义。Ws2tcpip.h 头文件包含 WinSock 2 协议特定附件文档中针对 TCP/IP 引入的定义,其中包括用于检索 IP 地址的较新的函数和结构。

#include <winsock2.h>
#include <ws2tcpip.h>

#pragma comment(lib, "Ws2_32.lib")

int main() 
{
   
  return 0;
}

Note: 如果需要使用 IP Helper APIs,需要包含 lphlpapi.h 头文件,但必须置于 Winsock2.h 头文件之后。 Winsock2.h 头文件内部包含了 Windows.h 中的核心元素,因此不需要再包含 Windows.h 头文件。如果需要包含 Windows.h 头文件,则需要定义宏  #define WIN32_LEAN_AND_MEAN。由于历史原因,Windows.h 标头默认包含 Windows Socket 1.1 的 Winsock.h 头文件。Winsock.h 头文件中的声明将与 Windows Socket 2.0 所需的Winsock2.h 头文件中的声明冲突。WIN32_LEAN_AND_MEAN 宏可防止 Winsock.h 包含在 Windows.h 头文件中。下面示例了一个说明这一点。

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>

#pragma comment(lib, "Ws2_32.lib")

int main() 
{
   
  return 0;
}

3. Initializing Winsock

调用 Winsock 函数的所有进程(应用或者 DLLs)都必须先初始化 Windows Sockets DLL。

这也用于确认系统是否支持 Winsock。

3.1 初始化 Winsock

  1. 创建一个 WSADATA 对象,名为 wsaData。
WSADATA wsaData;
  1. 调用 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 Sockets 的信息。WSAStartup 的 MAKEWORD(2,2) 参数在系统上发出对 Winsock 版本 2.2 的请求,并将传递的版本设置为调用方可以使用的最高版本的 Windows Sockets 支持。

4A. Winsock server application

4A.1 Create a Socket for Server

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

4A.1.1 To create a socket for the server
  1. [getaddrinfo](getaddrinfo function (ws2tcpip.h) - Win32 apps | Microsoft Learn) 函数用于决定 [sockaddr](sockaddr - Win32 apps | Microsoft Learn) 结构体中的值:
  • AF_INET 用于指定 IPv4 地址家族。

  • SOCK_STREAM 用于指定一个流 socket。

  • IPPROTO_TCP 用于指定 TCP 协议。

  • AI_PASSIVE flag 表明调用方打算在调用 bind 函数时使用返回 socket 地址结构。当 AI_PASSOVE flag 置位,并传给 getaddrinfo 函数的 nodename 参数为 NULL 指针,对于 IPv4 地址,socket 地址结构的 IP 地址部分为 INADDR_ANY。 而 IPv6 地址,socket 地址结构的 IP 地址部分为 IN6ADDR_ANY_INIT。

  • 27015 是与客户端将连接到的服务器关联的端口号。

// addrinfo 结构体被 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;
}
  1. 创建一个 SOCKET 对象,名为 ListenSocket,用于服务器监听客户端的连接。
SOCKET ListenSocket = INVALID_SOCKET;
  1. 调用 socket 函数,ListenSocket 变量用于接收函数返回值。对于这个服务器应用程序,采用 getaddrinfo 函数返回的第一个与 hints 参数设置相匹配的 IP 地址。

如果服务器应用程序希望监听 IPv6,则将 hints.ai_family = AF_INET6 即可。如果一个服务器希望同时监听 IPv4 和 IPv6,则必须创建两个监听 sockets。一个 IPv4,一个 IPv6,并且应用程序必须单独处理这两个 sockets 。

// Create a SOCKET for the server to listen for client connections
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
  1. 检查 socket,确保创建的 socket 有效。
if (ListenSocket == INVALID_SOCKET) 
{
   
    printf("Error at socket(): %ld\n", WSAGetLastError());
    freeaddrinfo(result);
    WSACleanup();
    return 1;
}

4A.2 Binding a Socket

要使服务器接受客户端连接,它必须绑定到系统中的网络地址。客户端应用程序使用 IP 地址和端口连接到主机网络。

sockaddr 结构体保存着 address family, IP address 和 port number。

调用 bind 函数,传入已创建的 socket 和 从 getaddrinfo 函数返回的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;
}

Note: 一旦 bind 函数被调用,getaddrinfo 函数返回的 address 信息将不再需要。调用 freeaddrinfo 函数释放 getaddrinfo 函数分配的内存空间。

freeaddrinfo(result);

4A.3 Listening on a Socket

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

调用 listen 函数,将创建的 socket 和 blacklog(要接受的挂起连接的队列的最大长度)值作为参数传递给 listen 函数。以下示例中,backlog 值设置为 SOMAXCONN。该值是一个特殊常量,指示 Winsock 提供程序为该 socket 允许队列中最大数量的挂起连接。检查常规错误的返回值。

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

4A.4 Accepting a Connection

socket 监听连接后,程序必须处理该 socket 上的连接请求。文章来源地址https://www.toymoban.com/news/detail-444212.html

4A.4.1 To accept a connection on a socket
  1. 创建一个临时的 SOCKET

到了这里,关于Windows 上的网络通信编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《3.linux应用编程和网络编程-第8部分-3.8.网络基础》 3.8.1.网络通信概述 3.8.3.网络通信基础知识2

        进程间通信: 管道 、 信号量、 共享内存, 技术多,操作麻烦     线程就是解决 进程间 通信 麻烦的事情,这是线程的 优势 3.8.1.网络通信概述 3.8.1.1、从进程间通信说起: 网络域套接字socket , 网络通信其实就是位于网络中不同主机上面                   的 

    2024年02月15日
    浏览(40)
  • Java 网络编程详解:实现网络通信的核心技术

    网络编程是指利用计算机网络进行数据交换和通信的过程。它涉及到在不同主机之间传输数据,并允许不同设备之间进行连接和通信。网络编程不仅限于互联网,也可以包括局域网或广域网等各种网络环境。 在当今的互联网时代,几乎所有的应用都需要在不同设备之间进行数

    2024年02月11日
    浏览(38)
  • 【网络编程】网络通信基础——简述TCP/IP协议

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】【Java系列】 本专栏旨在分享学习网络编程的一点学习心得,欢迎大家在评论区交流讨论💌 ip地址简单来说就是用来描述网络上一个设备的所在位置。 端

    2024年02月04日
    浏览(42)
  • 【Java】--网络编程:基于TCP协议的网络通信

    TCP协议(Transmission Control Protocol),即传输控制协议,是一种 面向连接 的, 可靠 的,基于 字节流 的传输层通信协议。数据大小无限制。 建立连接的过程需要 三次握手 。 断开连接的过程需要 四次挥手 。 使用TCP协议的通信双方分别为 客户端 和 服务器端 。 客户端负责向服务

    2024年01月23日
    浏览(47)
  • TCP网络通信编程之字符流

    【案例1】 【题目描述】 【 注意事项】 (3条消息) 节点流和处理流 字符处理流BufferedReader、BufferedWriter,字节处理流-BufferedInputStream和BufferedOutputStream (代码均正确且可运行_Studying~的博客-CSDN博客 1。这里需要使用字符处理流,来将字节流转为字符流。 使用的字符流,所以一定

    2024年02月15日
    浏览(27)
  • TCP网络通信编程之netstat

    【netstat指令】  【说明】 (1)Listening 表示某个端口在监听 (2)如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息 (3)指令netstat -anb 可以参看是那个程序在监听该端口,但是需要以管理员身份运行dos控制台。

    2024年02月15日
    浏览(29)
  • 网络编程之简单socket通信

    Socket,又叫套接字,是在应用层和传输层的一个抽象层。它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信。  socket分为流socket和数据报socket,分别基于tcp和udp实现。 SOCK_STREAM 有以下几个特征: 数据在传输过程中不会消失; 数据是按照顺序

    2024年02月01日
    浏览(34)
  • Java网络编程 - TCP通信

    快速入门(一发一收) TCP协议回顾 : TCP是一种面向连接,安全、可靠的传输数据的协议 传输前,采用“三次握手”方式,点对点通信,是可靠的 在连接中可进行大数据量的传输 TCP通信模式 : 在java中只要是使用java.net.Socket类实现通信,底层即是使用了TCP协议 编写客户端代码

    2024年01月19日
    浏览(37)
  • .NET网络编程——TCP通信

            就是将不同区域的电脑连接到一起,组成局域网、城域网或广域网。把分部在不同地理区域的计算机于专门的外部设备用通信线路 互联成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,共享硬件、软件、数据信息等资源。       

    2024年02月16日
    浏览(32)
  • 「网络编程」第二讲:网络编程socket套接字(三)_ 简单TCP网络通信程序的实现

    「前言」文章是关于网络编程的socket套接字方面的,上一篇是网络编程socket套接字(二),下面开始讲解!  「归属专栏」网络编程 「主页链接」个人主页 「笔者」枫叶先生(fy) 「枫叶先生有点文青病」「每篇一句」 I do not know where to go,but I have been on the road. 我不知

    2024年02月11日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包