戴上帽子 2021-03-18 14:23 采纳率: 0%
浏览 41

为什么客户端收不到服务端传来的消息

客户端代码

//IO多路复用技术select函数的使用 
#include<iostream>
#include<winsock.h>
#pragma comment(lib, "ws2_32.lib")

using namespace std;

void initialization();


int main()
{
	initialization();
	int ret;
	SOCKET cfd;
	SOCKADDR_IN srvAddr;
	char buf[FD_SETSIZE];

	cfd = socket(AF_INET, SOCK_STREAM, 0);
	if (cfd < 0)
	{
		perror("socket error");
	}

	memset(&srvAddr, 0, sizeof(srvAddr));
	srvAddr.sin_family = AF_INET;
	srvAddr.sin_port = htons(8888);
	srvAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");


	//连接
	ret = connect(cfd, (SOCKADDR*)&srvAddr, sizeof(srvAddr));
	if (ret == SOCKET_ERROR)
	{
		cout << "connect error" << endl;
	}

	while (1)
	{
		memset(buf, 0, sizeof(buf));
		cout << "请输入内容:";
		cin >> buf;
		send(cfd, buf, sizeof(buf), 0);
		memset(buf, sizeof(buf), 20);
		recv(cfd, buf, 20, 0);
		//cout << "接收到的信息:" << buf << endl;
		printf("%s\n", buf);
	}

	//关闭监听文件描述符
	closesocket(cfd);
	WSACleanup();
	system("pause");
	return 0;
}


void initialization()
{
	WORD w_req = MAKEWORD(2, 2);
	WSADATA wsadata;
	if (WSAStartup(w_req, &wsadata) != 0)
	{
		cout << "初始化套接字失败" << endl;
	}
	else
	{
		cout << "初始化套接字成功" << endl;
	}
}

服务端代码

//IO多路复用技术select函数的使用 
#include<iostream>
#include<winsock.h>
#pragma comment(lib, "ws2_32.lib")

using namespace std;

void initialization();


int main()
{

	initialization();
	int i;//for循环因子
	int ret;//bind和listen返回值
	int nready;//select返回值
	int len;//accept中cliaddrd的地址
	int rlen;//recv读取的字符长度
	char buf[FD_SETSIZE];
	fd_set tmpfds, rdfds; //要监控的文件描述符集
	SOCKET lfd, cfd;//socket和accept返回值
	SOCKADDR_IN svraddr, cliaddr;

	//创建socket
	lfd = socket(AF_INET, SOCK_STREAM, 0);
	if (lfd < 0)
	{
		perror("socket error");
		return -1;
	}

	//允许端口复用
	int opt = 1;
	setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(int));

	//绑定bind
	memset(&svraddr, 0, sizeof(svraddr));
	svraddr.sin_family = AF_INET;
	svraddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	svraddr.sin_port = htons(8888);
	ret = bind(lfd, (SOCKADDR*)&svraddr, sizeof(svraddr));
	if (ret < 0)
	{
		perror("bind error");
		return -1;
	}

	//监听listen
	ret = listen(lfd, 5);
	if (ret < 0)
	{
		perror("listen error");
		return -1;
	}

	//文件描述符集初始化
	FD_ZERO(&tmpfds);
	FD_ZERO(&rdfds);

	//将lfd加入到监控的读集合中
	FD_SET(lfd, &rdfds);


	//将监听文件描述符lfd加入到select监控中
	while (1)
	{
		//select为阻塞函数,若没有变化的文件描述符,就一直阻塞,若有事件发生则解除阻塞,函数返回
		//select的第二个参数tmpfds为输入输出参数,调用select完毕后这个集合中保留的是发生变化的文件描述符
		tmpfds = rdfds;
		nready = select(0, &tmpfds, NULL, NULL, NULL);
		if (nready <= 0)
		{
			continue;
		}
		
		memset(&cliaddr, 0, sizeof(svraddr));
		//发生变化的文件描述符有两类, 一类是监听的, 一类是用于数据通信的
		//监听文件描述符有变化, 有新的连接到来, 则accept新的连接
		for (i = 0; i < rdfds.fd_count; i++)
		{
			if (FD_ISSET(rdfds.fd_array[i], &tmpfds))
			{
				if (rdfds.fd_array[i] == lfd)
				{
					len = sizeof(cliaddr);
					cfd = accept(lfd, (SOCKADDR*)&cliaddr, &len);
					if (cfd < 0)
					{
						if (errno == ECONNABORTED || errno == EINTR)
						{
							continue;
						}
						break;
					}
					cout << "connect success" << endl;

					//将新的文件 描述符加入到select监控的文件描述符集合中
					FD_SET(cfd, &rdfds);
				}
				else//下面是通信的文件描述符有变化的情况
				{
					rlen = recv(rdfds.fd_array[i], buf, FD_SETSIZE, 0);
					if (rlen == 0)
					{
						FD_CLR(rdfds.fd_array[i], &rdfds);
						closesocket(tmpfds.fd_array[i]);
					}
					else
					{
						cout <<"server:"<< buf << endl;
						for (i = 0; i < rlen; i++)
						{
							buf[i] = toupper(buf[i]);
						}
						send(rdfds.fd_array[i], buf, rlen, 0);
						cout << "已发送:" << buf << endl;
						
					}
					closesocket(rdfds.fd_array[i]);
				}
			}
			
		}
	}

	//关闭监听文件描述符
	closesocket(lfd);
	WSACleanup();

	return 0;
}


void initialization()
{
	WORD w_req = MAKEWORD(2, 2);
	WSADATA wsadata;
	if (WSAStartup(w_req, &wsadata) != 0)
	{
		cout << "初始化套接字失败" << endl;
	}
	else
	{
		cout << "初始化套接字成功" << endl;
	}
}
  • 写回答

1条回答 默认 最新

  • 闻缺陷则喜何志丹 《深入浅出Visual c++》书籍作者 2023-10-03 08:49
    关注

    bind那就在无限等待了,也就是后面的代码不会执行。 bind和recive用不同的线程。

    评论 编辑记录

报告相同问题?

问题事件

  • 请详细说明问题背景 10月28日

悬赏问题

  • ¥100 求汇川机器人IRCB300控制器和示教器同版本升级固件
  • ¥15 用visualstudio2022创建vue项目后无法启动
  • ¥15 x趋于0时tanx-sinx极限可以拆开算吗
  • ¥500 把面具戴到人脸上,请大家贡献智慧
  • ¥15 任意一个散点图自己下载其js脚本文件并做成独立的案例页面,不要作在线的,要离线状态。
  • ¥15 各位 帮我看看如何写代码,打出来的图形要和如下图呈现的一样,急
  • ¥30 c#打开word开启修订并实时显示批注
  • ¥15 如何解决ldsc的这条报错/index error
  • ¥15 VS2022+WDK驱动开发环境
  • ¥30 关于#java#的问题,请各位专家解答!