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 @ 2022-10-26 18:30  hugeYlh  阅读(23)  评论(0编辑  收藏  举报  来源