华清远见作业第三十天——网络编程(第五天)

思维导图:

使用selsect实现TCP客户端的并发

代码

cpp 复制代码
#include<a.h>
#define SER_PORT  8888             //服务器端口号
#define SER_IP "192.168.125.50"    //服务器ip地址
#define CLI_PORT 6666                //客户端的端口号
#define CLI_IP "192.168.125.50"       //客户端ip地址


int main(int argc, const char *argv[])
{
	//1、创建用于通信的套接字文件描述符
    int cfd = -1;
    cfd = socket(AF_INET, SOCK_STREAM, 0);
    if(cfd == -1)
    {
        perror("socket error");
        return -1;
    }
    printf("cfd = %d\n", cfd);            //3

    //2、绑定(可选)
    //2.1 填充地址信息结构体 
    struct sockaddr_in cin;
    cin.sin_family = AF_INET;
    cin.sin_port = htons(CLI_PORT);
    cin.sin_addr.s_addr = inet_addr(CLI_IP);
    //2.2绑定
    if(bind(cfd, (struct sockaddr*)&cin, sizeof(cin)) == -1)
    {
        perror("bind error");
        return  -1;
    }
    printf("bind  success\n");
    
    //3、连接服务器
    //3.1 填充服务器地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family =     AF_INET;
    sin.sin_port =         htons(SER_PORT);
    sin.sin_addr.s_addr = inet_addr(SER_IP);
    //3.2 连接
    if(connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) == -1)
    {
        perror("connect error");
        return -1;
    }
    printf("连接成功\n");
    //准备一个文件描述器
	fd_set readfds,tempfds;//临时集合
	//清空容器
	FD_ZERO(&readfds);
	//将要检测的文件放入集合中
	FD_SET(0,&readfds);
	FD_SET(cfd,&readfds);
	int res=-1; //接收select函数对容器的中文件描述符号检测的返回值


    //4、收发数据
    char wbuf[128]=""; //终端
	char rbuf[128]=""; //接收服务器发来的消息
    while(1)
    {
		tempfds=readfds; //存储一份数据
		//使用select函数对容器中的文件描述符进行检测
		res=select(cfd+1,&tempfds,NULL,NULL,NULL);
		if(res==-1)
		{
			perror("select error");
			return -1;
		}else if(res==0)
		{
			printf("timeout\n");
			return -1;
		}
		//判断终端是否发生事件
		if(FD_ISSET(0,&tempfds))
		{
		
		
			//清空数组
			bzero(wbuf, sizeof(wbuf));

			printf("请输入>>>");
			fgets(wbuf, sizeof(wbuf), stdin);   //从终端输入数据
			wbuf[strlen(wbuf)-1] = 0;          //将换行改为'\0'

			//发送给服务器
			send(cfd, wbuf, sizeof(wbuf), 0);
			printf("发送成功\n");
			if(strcmp(wbuf, "quit") == 0)
			{
				break;
			}
		}
		//判断是否是服务器发来的消息触发
		if(FD_ISSET(cfd,&tempfds))
		{
		
			//清空数组
			bzero(rbuf,sizeof(rbuf));
			//接收服务器发来的消息
			recv(cfd, rbuf, sizeof(rbuf), 0);
			printf("[%s:%d]:%s\n", SER_IP, SER_PORT, rbuf);
		}
    }

    //5、关闭套接字
    close(cfd);

    return 0;
}
相关推荐
lularible18 小时前
PTP协议精讲(3.7):传输层实现——PTP报文的“高速公路“
网络·网络协议·开源·嵌入式·ptp
Sakuyu4346818 小时前
C语言基础(三)
c语言·开发语言
SilentSamsara19 小时前
Kubernetes 网络模型:CNI 插件与 Pod 间通信的底层实现
网络·云原生·容器·架构·kubernetes·k8s
渡己之道19 小时前
笔记-lvgl移植到stm32f407
c语言·笔记·stm32
我也不曾来过119 小时前
传输层协议UDP和TCP
linux·网络·udp
Legendary_00819 小时前
Type-C 赋能传统显示器:一线通联,LDR6020 重构显示互联体验
c语言·计算机外设·pd芯片
奇妙之二进制19 小时前
zmq源码分析之消息可读通知机制
服务器·网络
techdashen19 小时前
不开端口,不配 DNS,用树莓派在家搭一个公网可访问的 Web 服务
前端·网络·智能路由器
笨熊呆呆瓜19 小时前
【可靠性配置】华为M-LAG防环机制
网络
郑寿昌19 小时前
虚幻引擎UE5 Lumen兼容PBR材质全解析
服务器·网络·材质