tcp服务器接收数据

#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++;                                                            //粘包处理
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值