首页 > 编程语言 >基于Select模型的通信仿真--win32编程代码

基于Select模型的通信仿真--win32编程代码

时间:2024-11-18 18:07:12浏览次数:1  
标签:socket -- win32 int printf listen sin Select addr

目录

基于Select模型的通信仿真--win32编程代码

编程环境

Visual C++ 6.0

服务端

#include<stdio.h>
#include<string.h>
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	AllocConsole();
	freopen("CONOUT$","w",stdout);
	freopen("CONIN$", "r", stdin);
    freopen("CONOUT$", "w", stderr);
	// 初始化 Winsock
	WSADATA wsaData;
	int result=WSAStartup(MAKEWORD(2, 2), &wsaData);

	if (result != 0) 
	{
		 printf("WSAStartup failed with error: %d\n", result);
		 return 1;
	}

	//1.创建socket套接字
	/*
	SOCKET socket(
    _In_ int af,		//协议地址簇	IPv4:AF_INET/IPv6:AF_INET6
    _In_ int type,		//类型			流式协议:SOCK_STREAM/数据报协议:SOCK_DGRAM
    _In_ int protocol	//保护协议		上层协议tcp、udp不用写,填0即可
    );
	*/
	SOCKET listen_socket=socket(AF_INET, SOCK_STREAM, 0);
	if (INVALID_SOCKET==listen_socket)
	{
		printf("create listen socket failed!!! errcode: %d\n", GetLastError());
		WSACleanup();
		return -1;
	}

	//2.给socket绑定端口号
	/*
	* ip地址结构体
	struct sockaddr_in {
	ADDRESS_FAMILY sin_family;	//协议地址簇
    USHORT sin_port;			//端口号	2字节
    IN_ADDR sin_addr;			//ip地址	4字节
    CHAR sin_zero[8];			//保留字节	8字节
	};
	struct sockaddr {
	u_short sa_family;					//协议地址簇
	CHAR sa_data[14];                   //14字节
	}
	*/
	struct sockaddr_in local = {0};

	local.sin_family = AF_INET;
	local.sin_port = htons(8080);//绑定端口 大小端转化:中间设备使用大端序(路由器),但是电脑使用的是小端序,所以要转化
	/*
	电脑上有多个网卡,服务器可以选择接收哪个或哪些网卡传过来的数据。
	如:127.0.0.1(本地环回),则服务器只能和自己通信	INADDR_LOOPBACK
	一般写全0地址(0.0.0.0),表示接收全部网卡的数据	INADDR_ANY
	*/
	//local.sin_addr.s_addr = htonl(INADDR_ANY);//接收全部网卡的数据 大小端转化
	local.sin_addr.s_addr = inet_addr("0.0.0.0");//接收全部网卡的数据 字符串ip转成整数ip

	/*
	int bind(
    SOCKET s,							//绑定的套接字
    const struct sockaddr FAR * name,	//ip地址结构体
    int namelen							//ip地址结构体的长度
    );
	*/
	bind(listen_socket,(struct sockaddr*)&local,sizeof(local));

	//3.给socke开启监听属性,只用来接收连接
	/*
	int listen(
    _In_ SOCKET s,		//监听套接字
    _In_ int backlog	//
    );
	*/
	if (-1 == listen(listen_socket, 10))
	{
		printf("start listen failed!!! errcode: %d\n", GetLastError());
		WSACleanup();
		return -1;
	}
    fd_set redset;
    //4、初始化文件描述符集合  
    FD_ZERO(&redset);
    //5、添加要检测的监听文件描述符    
    FD_SET(listen_socket,&redset);

    
    printf("This is SERVER!\n");
    while (1)
    {
        fd_set tmp = redset;
        /* 6、不停地检测文件描述符
              6.1 超时  select() = 0 再次检测或关闭套接字
              6.2 异常  select() = -1 异常处理
              6.3 成功  selct() >0
       */
        printf("selecting...\n");
        int ret = select(-1, &tmp, NULL, NULL, NULL);
        if (ret <= 0)
        {
            printf("select failed!!! errcode: %d\n", GetLastError());
            closesocket(listen_socket);
            WSACleanup();
            return -1;
        }
       // printf("select = %d\n",ret);
        //7、判断文件描述符属于哪一类
            //通过将原来redset集合中的文件描述符与select处理过的tmp集合比较,判断哪些文件描述符就绪,如果就绪,是哪一类
        for (int i = 0; i < (int)redset.fd_count; i++)
        {
            if (FD_ISSET(redset.fd_array[i], &tmp))//判断文件描述符(套接字)i的读缓冲区是否有数据
            {
                //就绪文件描述符是监听描述符
                if (redset.fd_array[i] == listen_socket)    // 监听套接字接收到新连接
                {
                    if (redset.fd_count < FD_SETSIZE)
                    {
                        sockaddr_in addrRemote;
                        int nAddrLen = sizeof(addrRemote);
                        //接收客户端的连接请求
                        SOCKET client_socket = ::accept(listen_socket, (SOCKADDR*)&addrRemote, &nAddrLen);
                        FD_SET(client_socket, &redset);
                        printf("与主机 %s 建立连接\n", inet_ntoa(addrRemote.sin_addr));
                    }
                    else
                    {
                        printf("Too much connections!\n");
                        continue;
                    }
                }
                else//就绪文件描述符不是监听描述符,是通信描述符
                {
                    //接收信息
                    char rbuffer[1024] = { 0 };
                    int len = recv(redset.fd_array[i], rbuffer, 1024, 0);

                    if (len <= 0)
                    {
                        printf("The client %d has disconnected.\n", i);
                        FD_CLR(redset.fd_array[i], &redset);
                        shutdown(redset.fd_array[i], SD_BOTH);
                        closesocket(redset.fd_array[i]);
                        break;
                    }
                    printf("recive from client%d:\t%s\n", i, rbuffer);

                    //发送信息
                    char sbuffer[1024] = { 0 };
                    // 检查接收到的消息
                    if (strcmp(rbuffer, "计算从1到100的奇数和") == 0)
                    {
                        int sum = 0;
                        for (int j = 1; j <= 100; j += 2)
                        {
                            sum += j;
                        }
                        printf("send to client%d:\t1到100的奇数和是 %d\n", i, sum);

                        sprintf(sbuffer, "1到100的奇数和是 %d\n", sum);
                    }
                    else
                    {
                        printf("send to client%d:\tunknow!\n", i);
                        sprintf(sbuffer, "unknow!");
                    }

                    len = send(redset.fd_array[i], sbuffer, strlen(sbuffer), 0);
                    if (len == -1)
                    {
                        perror("send error");
                        exit(1);
                    }
                   
                }
            }
        }
    }

    closesocket(listen_socket);
	FreeConsole();
	// 清理 Winsock
    WSACleanup();


	return 0;
}

客户端

#include<stdio.h>
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	AllocConsole();
	freopen("CONOUT$","w",stdout);
	freopen("CONIN$", "r", stdin);
    freopen("CONOUT$", "w", stderr);
	// 初始化 Winsock
	WSADATA wsaData;
	int result=WSAStartup(MAKEWORD(2, 2), &wsaData);

	if (result != 0) 
	{
		 printf("WSAStartup failed with error: %d\n", result);
		 return 1;
	}

	//1.创建socket套接字
	SOCKET client_socket = socket(AF_INET, SOCK_STREAM, 0);
	if (INVALID_SOCKET == client_socket)
	{
		printf("create socket failed!!! errcode: %d\n", GetLastError());
		WSACleanup();
		return -1;
	}
	//2.连接服务器
	struct sockaddr_in target;//目标服务器的ip结构体
	target.sin_family = AF_INET;
	target.sin_port = htons(8080);
	target.sin_addr.s_addr = inet_addr("127.0.0.1");

	if (-1 == connect(client_socket, (struct sockaddr*)&target, sizeof(target)))
	{
		printf("connect server failed!!!\n");
		shutdown(client_socket, SD_BOTH);
		closesocket(client_socket);
		WSACleanup();
		return -1;
	}
	//3.开始通讯

	printf("This is  Cilent1.\n\n");
	while (1)
	{
		//发送信息
		printf("send:\t");
		char sbuffer[1024] = { 0 };
		scanf("%s", sbuffer);
		send(client_socket, sbuffer, strlen(sbuffer),0);

		//接收消息
		char rbuffer[1024] = { 0 };
		int ret=recv(client_socket, rbuffer, 1024, 0);
		if (ret <= 0)
		{
			break;//断开连接
		}
		printf("recive:\t%s\n", rbuffer);
	}
	
	//4.关闭连接
	shutdown(client_socket, SD_BOTH);shutdown(client_socket, SD_BOTH);
	closesocket(client_socket);
	
	FreeConsole();
	// 清理 Winsock
    WSACleanup();


	return 0;
}

标签:socket,--,win32,int,printf,listen,sin,Select,addr
From: https://www.cnblogs.com/wa2211lq/p/18553351

相关文章

  • 实验4 类的组合、继承、模板类、标准库
    任务2源码:1#include<iostream>2#include<vector>3#include<string>4#include<algorithm>5#include<numeric>6#include<iomanip>78usingstd::vector;9usingstd::string;10usingstd::cin;......
  • 2.3
    importnumpyasnpimportmatplotlib.pyplotasplt定义x的范围x=np.linspace(-10,10,400)创建一个图形和坐标轴plt.figure(figsize=(10,6))ax=plt.gca()循环绘制每条曲线colors=['r','g','b','c','m','y']#定......
  • 显示本站建立多久了
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>本网站已建立</title></head><body><h1id="time"></h1></body></html><scrip......
  • 2.6
    importnumpyasnpimportmatplotlib.pyplotaspltfrommpl_toolkits.mplot3dimportAxes3D模拟高程数据(假设数据已经过某种方式插值或生成)这里我们创建一个简单的40x50网格,并填充随机高程值x=np.linspace(0,43.65,40)y=np.linspace(0,58.2,50)X,Y=np.meshgr......
  • Linux文件隐藏属性及chattr和lsattr命令
    文件属性配置问题。chattr命令[root@ashlafkasjfkqyuezc]#chattr[+-=][ASacdistu]文件或目录名称选项与参数: +:增加某一个特殊参数,其他原本存在参数则不动。 -:移除某一个特殊参数,其他原本存在参数则不动。 =:设置等于,且仅有后面接的参数 A:当设置了A这个属性时,若你......
  • 精准测试如何落地
    在当今快速迭代的软件开发环境中,测试的效率与质量成为了决定产品竞争力的关键因素之一。精准测试,作为一种高效、针对性的测试方法,正逐步成为众多企业的首选。本文将深入探讨精准测试如何落地、其对质量指标的影响、落地过程的数据统计方法、跟踪度量落地效果的途径、提高投入产出......
  • 服务端性能优化
    优化代码优化识别出性能瓶颈点循环优化算法优化减少函数调用内存管理并发和多线程代码重构编译器优化缓存优化内存缓存分布式缓存浏览器缓存cdn缓存缓存粒度控制缓存失效策略缓存预热缓存一致性异步优化非阻塞操作提高资源利用率多线程优化线......
  • Express的使用笔记8 引入验证中间件来给表单添加验证规则~
    前面已经将数据成功写入了数据库了,接下来就开始探讨接口传递参数的校验咯~自己封装虽然灵活,但也常常架不住有现成的,既灵活又方便,比如:express-valiation官方文档地址:https://express-validator.github.io/docs/guides/schema-validation先安装咯!npmiexpress-valiation引入......
  • 银河护胃队-冲刺日志(第一天)
    作业所属课程https://edu.cnblogs.com/campus/fzu/SE2024/作业要求https://edu.cnblogs.com/campus/fzu/SE2024/homework/13305作业的目标2024-11-11冲刺日志,记录每天的冲刺会议与进度团队名称银河护胃队团队成员学号-名字072208130-曹星才(组长)052205144-张......
  • FMC子卡设计原理图:FMC-707双通道250Msps采集和双通道12.6Gsps回放
    UDFMC-707双通道接收+双通道发射FMC模块满足VITA57.1单宽、导冷规范。模块ADC支持进口AD9467-250或国产采集芯片,DAC支持AD9171/AD9172/AD9173/AD9174/AD9175/AD9176回放芯片,输入和输出均为交流耦合方式。FMC子卡还支持外参考/外时钟、外触发接口,具有板载温度监控等功能。模块采......