windows网络编程 ---网络聊天室(1)

一个简单的网络聊天室

运行如下:
在这里插入图片描述

只是实现了一个简单的通信功能,下一节我们再来讨论的IO/CP模型

服务器端

  1. 初始化网络环境
int WSAAPI WSAStartup(
[in] WORD wVersionRequested, //windows套接字规范
[out] LPWSADATA lpWSAData //WSADATA的结构体指针
);

此函数用来初始化网络环境,通过进程启动 Winsock DLL 的使用。

  • 第一个参数用来指定版本号,我们通常使用MAKEWORD来表示,高顺序字节指定次要版本号;低顺序字节指定主版本号
  • 第二个参数是一个结构体的指针,该结构用于接收 Windows 套接字实现的详细信息(对我们这个项目来说意义不大)

  1. 创建socket套接字
SOCKET WSAAPI socket(
[in] int af, //地址族规范
[in] int type, //套接字的类型规范
[in] int protocol //要使用的协议
);

创建绑定到特定传输服务提供者的套接字。

  • 第一个参数:地址族规范,我们可以指定使用什么地址族类型,比如说AF_INET:表示使用IPV4 或者IPV6
  • 第二个参数:套接字规范,例如我们使用SOCK_STREAM:表示指定套接字接收IPV4和6的数据流
  • 第三个参数:传输控制协议,IPPROTO_TCP:指定IPV4和6的通信协议。

  1. 绑定套接字和IP地址
INT WSAAPI inet_pton(
[in] INT Family, //地址族
[in] PCSTR pszAddrString,//要转换成文本形式的IP地址
[out] PVOID pAddrBuf //IP地址接收的缓冲区
);
int WSAAPI bind(
[in] SOCKET s, //套接字
[in] const sockaddr *name,//要分配给套接字的本地地址名称(一个sockaddr_in结构体)
[in] int namelen//长度
);

首先inet_pton将标准文本呈现形式中将 IPv4 或 IPv6 Internet 网络地址转换为其数字二进制形式,然后使用bind绑定函数将本地地址与套接字相关联。

inet_pton

  • 第一个参数: 地址族的规范:使用AF_INET
  • 第二个参数:你电脑的IP地址,把这个IP转换为文本型。
  • 第三个参数:你将要把这个转换后的IP地址放到什么位置,放到一个sockaddr_in的结构体中

bind:

  • 第一个参数:一开始指定的套接字
  • 第二个参数:要和套接字绑定的IP地址,不过它接收一个sockaddr_in的结构体,我们在inet_pton刚把这个IP地址放入在这个结构体中。
  • 第三个参数:结构体的大小。

  1. 监听套接字
int WSAAPI listen(
[in] SOCKET s,
[in] int backlog
);

listen: 将套接字置为监听消息的状态。

  • 第一个参数: 你指定的套接字
  • 第二个参数:挂起连接队列的最大长度,使用SOMAXCONN即可,系统默认。

  1. 接收与发送消息
SOCKET WSAAPI accept(
[in] SOCKET s,
[out] sockaddr *addr,
[in, out] int *addrlen
);
int WSAAPI recv(
[in] SOCKET s,
[out] char *buf,
[in] int len,
[in] int flags
);
int WSAAPI send(
[in] SOCKET s,
[in] const char *buf,
[in] int len,
[in] int flags
);

accept :连接客户端,侦听客户端消息。
recv : 接收数据。
send:发送数据。

accept :

  • 第一个参数:刚才你listen的套接字
  • 第二个参数:指向接收连接实体地址的缓冲区的可选指针,实际上就是连接客户端的一个结构体。
  • 第三个参数:结构体大小。

recv send:接收数据,发送数据 ,很简单,不多说


代码

#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
int main()
{
//1. 初始化网络环境
WSADATA WsaData{ 0 };
WSAStartup(
MAKEWORD(2, 2), //套接字
&WsaData
);
//2. 创建socket套接字
//创建绑定到特定传输服务提供者的套接字。
SOCKET serve = socket(
AF_INET,
SOCK_STREAM,
IPPROTO_TCP
);
//3. 绑定端口号IP地址
sockaddr_in serverAddr{ 0 };
serverAddr.sin_family = AF_INET; //地址族
serverAddr.sin_port = htons(666); //端口号
//inet_pton:标准文本呈现形式中将 IPv4 或 IPv6 Internet 网络地址转换为其数字二进制形式
inet_pton(AF_INET, "172.20.230.126", &serverAddr.sin_addr);
//bind:绑定函数将本地地址与套接字相关联。
bind(serve, (sockaddr*)&serverAddr, sizeof(serverAddr));
//4. 监听
//侦听函数将套接字置于侦听传入连接的状态。
listen(serve, SOMAXCONN);
sockaddr_in ClientAddr{ 0 };
int SockSize = sizeof(ClientAddr);
//5. 接收会话
while (1)
{
SOCKET client = accept(
serve, //标识已使用监听函数处于侦听状态的套接字
(sockaddr*)&ClientAddr,
&SockSize
);
WCHAR lpBuff[0x100]{ 0 };
//接收: recv:从连接的套接字或绑定的无连接套接字接收数据。
recv(client, (CHAR*)lpBuff, 0x100, NULL);
printf("客户:%s\n", lpBuff);
//发送: send:在连接的套接字上发送数据。
send(client, "欢迎您加入聊天", 14, NULL);
}
closesocket(serve);
system("pause");
return 0;
}

客户端

客户端的前几步的步骤和服务器端一摸一样,都要有初始化网络环境创建SOCKET套接字

  1. 连接 指定的套接字IP地址
ient_pton: IP地址转换
int WSAAPI connect(
[in] SOCKET s, //客户端的套接字
[in] const sockaddr *name,//应建立连接的sockaddr结构体指针
[in] int namelen//结构体大小
);

connect: 建立与指定套接字的连接,实际上就是建立客户端与服务器的连接。


  1. 发送与接收消息
recv
send

代码

#include <WinSock2.h>
#include <Windows.h>
#include <WS2tcpip.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
int main()
{
//1. 初始化网络连接
WSADATA WsaData{ 0 };
WSAStartup(MAKEWORD(2, 2), &WsaData);
//2. 创建SOCKET套接字
SOCKET serve = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//3. 绑定IP地址
sockaddr_in serveAddr{ 0 };
serveAddr.sin_family = AF_INET; //地址族
serveAddr.sin_port = htons(666); //端口号
inet_pton(AF_INET, "172.20.230.126",&serveAddr.sin_addr);
//连接服务器
//connect函数建立与指定套接字的连接。
int result = connect(serve, (sockaddr*)&serveAddr, sizeof(serveAddr));
if (result != 0) //未发生错误,返回零
{
printf("连接失败!\n");
system("pause");
return 0;
}
send(serve, "你好啊服务器", 12, NULL);
CHAR recvBuff[0x100]{ 0 };
recv(serve, recvBuff, 0x100, NULL);
printf("服务器说:%s\n", recvBuff);
system("pause");
closesocket(serve);
return 0;
}

两个项目同时生成,首先打开服务器端exe,然后再次打开客户端,就可以做到服务器端和客户端同时相互发送消息了。

posted @   hugeYlh  阅读(54)  评论(0编辑  收藏  举报  
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示