Linux下网络编程-简易Epll服务器和客户端

Linux下网络编程-简易Epll服务器和客户端

简易Epll服务器:
cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>

#define BUF_SIZE 100
#define EPOLL_SIZE 50
void error_handling(const char *buf);

int main(int argc, char *argv[])
{
    if(argc!=2) 
    {
		printf("Usage : %s <port>\n", argv[0]);
		exit(1);
	}

    int serv_sock, clnt_sock;
	struct sockaddr_in serv_adr, clnt_adr;
	socklen_t adr_sz;
	int str_len, i;
	char buf[BUF_SIZE];

    serv_sock=socket(PF_INET, SOCK_STREAM, 0);
	memset(&serv_adr, 0, sizeof(serv_adr));
	serv_adr.sin_family=AF_INET;
	serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
	serv_adr.sin_port=htons(atoi(argv[1]));

    if(bind(serv_sock, (struct sockaddr*) &serv_adr, sizeof(serv_adr))==-1)
		error_handling("bind() error");
	if(listen(serv_sock, 5)==-1)
		error_handling("listen() error");

    epoll_event event;
    int epfd,event_count;
    epfd=epoll_create(100);
    if(epfd==-1)
    {
        error_handling("epoll_create() failed");
        close(serv_sock);
    }
        
    epoll_event* all_events=new epoll_event[EPOLL_SIZE];
    event.events=EPOLLIN;//默认是设置条件触发方式
    event.data.fd=serv_sock;
    epoll_ctl(epfd,EPOLL_CTL_ADD,serv_sock,&event);

    while(1)
    {
        event_count=epoll_wait(epfd,all_events,EPOLL_SIZE,-1);
        if(event_count==-1)
        {
            puts("epoll_wait() error\n");
            break;
        }

        for(int i=0;i<event_count;i++)
        {
            if(all_events[i].data.fd==serv_sock)
            {
                adr_sz=sizeof(clnt_adr);
                clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_adr,&adr_sz);
                event.events=EPOLLIN;
                event.data.fd=clnt_sock;
                epoll_ctl(epfd,EPOLL_CTL_ADD,clnt_sock,&event);
                printf("connected client: %d \n", clnt_sock);
            }
            else
            {
                str_len=read(all_events[i].data.fd,buf,BUF_SIZE);
                if(str_len==0)//关闭请求
                {
                    epoll_ctl(epfd,EPOLL_CTL_DEL,all_events[i].data.fd,NULL);
                    close(all_events[i].data.fd);
                    printf("closed client:%d\n",all_events[i].data.fd);
                }   
                else
                {
                    write(all_events[i].data.fd,buf,BUF_SIZE);
                }
            }
        }
    }

    delete[] all_events;
    close(serv_sock);
    close(epfd);
    return 0;
}

void error_handling(const char *buf)
{
	fputs(buf, stderr);
	fputc('\n', stderr);
	exit(1);
}
简易客户端:
cpp 复制代码
//编译命令:g++ -g PThreadSocketClient.cpp -o PThreadSocketClient -lpthread
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>

#define BUF_SIZE 100
#define NAME_SIZE 20

char name[NAME_SIZE]="[DEFAULT]";
char msg[BUF_SIZE];

void* send_msg(void * arg);
void* recv_msg(void * arg);
void error_handling(const char * msg);

int main(int argc, char *argv[])
{
	int sock;
	struct sockaddr_in serv_addr;
	pthread_t snd_thread, rcv_thread;
	void * thread_return;

    if(argc!=4) 
    {
		printf("Usage : %s <IP> <port> <name>\n", argv[0]);
		exit(1);
	 }

	sprintf(name, "[%s]", argv[3]);
	sock=socket(PF_INET, SOCK_STREAM, 0);
	
	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family=AF_INET;
	serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
	serv_addr.sin_port=htons(atoi(argv[2]));
	  
	if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1)
		error_handling("connect() error");

	pthread_create(&snd_thread,NULL,send_msg,(void*)&sock);
	pthread_create(&rcv_thread,NULL,recv_msg,(void*)&sock);
	pthread_join(snd_thread,&thread_return);
	pthread_join(rcv_thread,&thread_return);
	close(sock);
    return 0;
}

void* send_msg(void * arg)
{
	int sock=*(int *)arg;
	char name_msg[NAME_SIZE+BUF_SIZE];
	while(1)
	{
		fgets(msg,BUF_SIZE,stdin);
		if(!strcmp(msg,"q\n")||!strcmp(msg,"Q\n"))
		{
			close(sock);
			exit(0);
		}
		sprintf(name_msg,"%s %s",name,msg);
		write(sock,name_msg,strlen(name_msg));
	}
	return NULL;
}

void* recv_msg(void * arg)
{
	int sock=*(int *)arg;
	char name_msg[NAME_SIZE+BUF_SIZE];
	int str_len;
	while(1)
	{
		str_len=read(sock,name_msg,NAME_SIZE+BUF_SIZE-1);
		if(str_len==-1)
		{
			return (void*)-1;
		}
		name_msg[str_len]=0;
		fputs(name_msg,stdout);
	}
	return NULL;
}

void error_handling(const char * msg)
{
    fputs(msg, stderr);
	fputc('\n', stderr);
	exit(1);
}
相关推荐
米糕闯编程3 分钟前
鱼香ros2(十七)C++小海龟巡逻
开发语言·c++·机器人·ros2·服务·小海龟
梦帮科技27 分钟前
Web 漏洞攻防深度:WAF 规则逃逸技术(畸形分块传输、双重编码)与对抗加固
linux·前端·网络安全·ssl·web
for_ever_love__32 分钟前
忠实度(Faithfulness):怎么判断 RAG 的答案有没有瞎编
linux·rag·评估·答案·faithfulness·原文·忠实度
程序员-Benothing44 分钟前
Linux系统监控工具全家桶:sar、dstat、glances、Prometheus
linux·运维·prometheus
栈帧之外1 小时前
【C++】红黑树实现
开发语言·c++
程序员老陆1 小时前
C++中同一个回调函数被多个设备并发调用:并发问题不在“函数”,而在“状态”
开发语言·c++·程序设计
辛苦才能1 小时前
C++ unordered_map/set 深度解析:快在O(1),输在无序,与map/set怎么选
c++·哈希算法·散列表
瑞克-桑切斯2 小时前
13、DNS、DHCP 与 FTP 协议详解
linux·运维·云计算
程序员-Benothing2 小时前
Linux性能分析方法论:USE、RED、火焰图与perf实战
linux·运维·服务器
云中双月2 小时前
瑞芯微rv1106进入Loader模式转储emmc数据
linux·嵌入式·uboot·u-boot·emmc·rockchip·烧录·rv1106·瑞芯微