有名管道实现单向通信

简单逻辑

客户端发送数据,服务器接收数据,可以通过ctrl+c或客户端输入quit进行停止通信

注意点

1.有名管道的实现
2.strlen(),sizeof()对字符串的处理
3.缓存溢出

代码及实现

在这里插入图片描述

makefile
.PHONY : all
all : server client

server : qq_server.cpp
	g++ -std=c++11  qq_server.cpp -o server
client : qq_client.cpp
	g++ -std=c++11  qq_client.cpp -o client

.PHONY:clean
clean:
	rm -f server client
头文件comm.hpp
#pragma once

#include <stdint.h>
#include <iostream>
#include <string>

const std::string fifoname="./fifo";
//所有用户有读写权限
uint32_t mode =0666;

#define NUM 1024
客户端qq_client.cpp
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>
#include "comm.hpp"

int main(){
    int wfd=open(fifoname.c_str(),O_WRONLY);
    if(wfd<0){
        std::cout<<"have error :"<<strerror(errno)<<std::endl;
        return 1;
    }

    char buffer[NUM];
    while(true){
        std::cout<<"请输入消息: ";
        //fgets结尾会自动加入\0
        char* msg = fgets(buffer,sizeof(buffer),stdin);
        //fgets接收数据后结尾为\n\0
        //断言空指针
        assert(msg);
        (void)msg;
        //防止回车被读入缓冲区
        //将回车位置替换为0及结尾为\0
        buffer[strlen(buffer)-1]=0;
		//当客户端输入quit时结束循环
        if(strcasecmp(buffer,"quit")==0){
            break;
        }
        ssize_t n=write (wfd,buffer,strlen(buffer));
        
        assert(n>=0);
        (void)n;
    }
    close(wfd);
    return 0;
}
服务器端qq_server.cpp
#include <unistd.h>
#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include "comm.hpp"
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <typeinfo>


volatile sig_atomic_t flag =0;

void funsig(int signum){
    flag= 1;
}
int main(){
    umask(0);
    //int mkfifo(const char *pathname, mode_t mode);
    //c_str()将stirng->char
    int n=mkfifo(fifoname.c_str(),mode);
    
    if(n!=0){
        std::cout<<"have error :"<< strerror(errno)<<std::endl;
        return 1;
    }
    //std::cout<<"create fifo success"<<std::endl;
    
    int rfd=open(fifoname.c_str(),O_RDONLY);
    if(rfd<=0){
        std::cout<<"have error :"<<strerror(errno)<<std::endl;
        return 2;
    }
    //std::cout<<"open fifo success"<<std::endl;
    signal(SIGINT,funsig);    
    
    char buffer[NUM];
    while(true){
        //初始化
        buffer[0]=0;
        if(1==flag){
           break;
        }
        //不读入\0
        ssize_t n=read(rfd,buffer,sizeof(buffer)-1);

        if(n>0){
        	//在数据结尾放\0,按c语言标准打印,c语言字符串必须以\0结尾
            buffer[n]=0;
            std::cout<<buffer<<std::endl;
        }
        else if(n==0){
            std::cout<<"client quit"<<std::endl;
            break;
        }
        else{
            std::cout<<"have error :"<<strerror(errno)<<std::endl;
            break;
        }
    } 
    close(rfd);
    unlink(fifoname.c_str());
    return 0;
} 

总结

  1. strlen、sizeof区别
  • strlen 遇到 \0 停止读取,取值不计算 \0
  • sizeof 取值将 \0 计算在内
int main() {
	
		char  val[] = "asd\0";
		char  val2[] = { 1,2,3,NULL,4,5,0 };

		cout << sizeof(val) << endl;//5
		cout << strlen(val) << endl;//3

		cout << sizeof(val2) << endl;//7
		cout << strlen(val2) << endl;//3
		return 0;
}
  • sizeof 内存中占用的字节数
  • strlen 实际长度
char str[20]=0123456789;
int a=strlen(str);  // a=10
int b=sizeof(str)  // b=20
  1. volatie 和 sig_atomic_t
  • volatie
    告诉编辑器数据随时会发生变化,使用前需要从地址中取值
  • sig_atomic_t
    确保在信号处理过程中可以原子地访问变量。
    原子访问优点:
    信号处理器可能在程序的任何时刻中断正常的执行流程。使用sig_atomic_t类型声明的变量可以确保在信号处理器中对其进行读取和修改时,这些操作是原子的。原子操作意味着在执行期间不会被其他信号中断,从而避免了数据竞争和不确定的行为。
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值