#include<sys/types.h>
#include<sys/socket.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/epoll.h>
int Socket(int domain,int type,int protocol);
int Bind(int sockfd,struct sockaddr * my_addr,int addrlen);
int Listen(int s,int backlog);
int Accept(int s,struct sockaddr * addr,int * addrlen);
void Deal_with_len(int recvid,char * readbuff);
typedef struct sockaddr SA; //通用地址结构
typedef struct sockaddr_in SIN;//IPV4地址结构
//设备信息列表
typedef struct{
int fd;
int devino;
int flags;
}FDFORDEV;
//文件描述符与设备信息列表
FDFORDEV fdfordev[1024];
//app IP地址 端口号
int main(int argc,char**argv)
{
memset(fdfordev,0,sizeof(fdfordev));
//建立监听套接字
int socketid = Socket(AF_INET,SOCK_STREAM,0);
//编写服务器信息
SIN my_addr;
my_addr.sin_family = AF_INET; //IPV4协议
my_addr.sin_port = htons(atoi(argv[2]));//大端序
my_addr.sin_addr.s_addr= inet_addr(argv[1]);//IP地址
int reuse=1;
setsockopt(socketid,SOL_SOCKET ,SO_REUSEADDR,(const char*)& reuse,sizeof(int));//允许套接字重用,主要用于服务器套接字,放在bind之前。
//绑定服务器信息
int addrlen = sizeof(SIN);
Bind(socketid, (SA*)&my_addr,addrlen);
//监听
Listen(socketid,100);
SIN client_addr;
int client_len = sizeof(SIN);
/*****************************epoll****************/
int epollfd = epoll_create(1024);
printf("epollfd:%d\n",epollfd);
struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = socketid;
int val = epoll_ctl(epollfd,EPOLL_CTL_ADD,socketid,&event);
if(val== -1)
{
perror("epoll_ctl");
exit(0);
}
//通信
while(1)
{
struct epoll_event events[10];
int count = epoll_wait(epollfd,events,10,-1);
if(count > 0)
{
for(int i =0; i < count;i++)
{
//判断 accept
if(events[i].data.fd == socketid)
{
SIN client;
struct epoll_event newevent;
int addrlen = sizeof(SA);
int newfd = Accept(socketid,(SA*)&client,&addrlen);
printf("%d客户端连接\n",newfd);
printf("\033[5m\033[45;33m HELLO_WORLD \033[0m\n");
newevent.events=EPOLLIN;
newevent.data.fd = newfd;
epoll_ctl(epollfd,EPOLL_CTL_ADD,newfd,&newevent);
}
//read
else
{
char readbuff[1024]={0};
int len = read(events[i].data.fd,readbuff,sizeof(readbuff));
if(len >0)
{
printf("%d:%s\n",events[i].data.fd,readbuff);
Deal_with_len(events[i].data.fd,readbuff);
}
else if(len ==0)
{
printf("%d:正常退出\n",events[i].data.fd);
epoll_ctl(epollfd,EPOLL_CTL_DEL,events[i].data.fd,NULL);
close(events[i].data.fd);
fdfordev[events[i].data.fd].fd = 0;
}
else
{
printf("%d:异常退出\n",events[i].data.fd);
epoll_ctl(epollfd,EPOLL_CTL_DEL,events[i].data.fd,NULL);
close(events[i].data.fd);
fdfordev[events[i].data.fd].fd =0;
}
}
}
}
}
return 0;
}
//包裹函数
int Socket(int domain,int type,int protocol)
{
int socketID = socket(domain,type,protocol);
if(socketID == -1)
{
perror("socket");
exit(0);
}
return socketID;
}
int Bind(int sockfd,struct sockaddr * my_addr,int addrlen)
{
int val = bind(sockfd,my_addr,addrlen);
if(val == -1)
{
perror("bind");
exit(0);
}
return 0;
}
int Listen(int s,int backlog)
{
int val = listen(s,backlog);
if(val == -1)
{
perror("bind");
exit(0);
}
return 0;
}
int Accept(int s,struct sockaddr * addr,int * addrlen)
{
int Newid = accept(s, addr, addrlen);
if(Newid == -1)
{
perror("accept");
exit(0);
}
return Newid;
}
//0xff 0xfe 0x长度高8位 0x长度低8位 0x自身设备ID高8位 0x自身设备ID低8位 0x对方设备ID高8位 0x对方设备ID低8位 0x在线状态 内容 0xfe 0xff
void Deal_with_len(int recvid,char * readbuff)
{
char * readp = (char *)readbuff;
while(*readp != 0)
{
//对比协议包头部分
if(((unsigned char)readp[0] == 0xff)&&((unsigned char)readp[1] == 0xfe))
{
//获取整个协议数据长度
short len = readp[2]<<8|readp[3];
//获取协议尾部
if(((unsigned char)readp[len-1]==0xff)&&((unsigned char)readp[len-2]==0xfe))
{
//发送方文件描述符
fdfordev[recvid].fd = recvid;
//发送方设备节点编号
fdfordev[recvid].devino = readp[4]<<8|readp[5];
//接收方设备编号
short recvdevid = readp[6]<<8|readp[7];
//接收方设备编号为0则服务器处理
if(recvdevid == 0)
{
//本机操作
printf("本机已接到\n");
}
//转发消息
else
{
int sendflag =0;
printf("转发消息\n");
//遍历设备信息及文件描述符列表
for(int j = 0; j < 1024; j++)
{
if((fdfordev[j].devino == devid)&&(fdfordev[j].fd != 0))
{
readp[8] = 0x01; //在线
write(fdfordev[j].fd,readp,len);
printf("转发对方\n");
break;
}
if(j == 1023)
{
sendflag =1;
}
}
//无该设备信息返回发送方不在线协议报
if(sendflag)
{
//0xff 0xfe 0x长度高8位 0x长度低8位 0x自身设备ID高8位 0x自身设备ID低8位 0x对方设备ID高8位 0x对方设备ID低8位 0x在线状态 内容 0xfe 0xff
readp[8] = 0x00; //不在线
readp[6] = readp[4];
readp[7] = readp[5];
readp[4]=0xff;
readp[5]=0xff;
write(recvid,readp,len);
printf("转发自己\n");
}
}
readp=&readp[len];
}
else
{
readp++; //粘包处理
}
}
else
{
readp++; //粘包处理
}
}
}