“深入浅出”系列之Linux:(4)后端服务器demo

server.cpp:
 

#include<iostream>
#include<cstdlib>
#include<sys/types.h> 
#include<sys/stat.h>
#include<netinet/in.h>  
#include<sys/socket.h> 
#include<string.h>
#include<unistd.h>
#include<signal.h>
#include<sys/ipc.h>
#include<cerrno>
#include<sys/shm.h>
#include<ctime>
#include<pthread.h>
#include<arpa/inet.h>
#define PORT 4395
#define SIZE 1024
#define SIZE_SHMADD 2048
#define BACKLOG 3
int sockfd;
int fd[BACKLOG];
int i=0;

/*********套接字描述符*******/
int get_sockfd()
{    
    sockaddr_in server_addr; 
    if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)  
    {    
        std::cerr<<"Socket error:"<<strerror(errno)<<"\n\a";          
        exit(1); 
    }else{
        std::cout<<"Socket successful!\n"; 
    }     
    /*sockaddr结构 */ 
    bzero(&server_addr,sizeof(sockaddr_in)); 
    server_addr.sin_family=AF_INET;                
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY); 
    server_addr.sin_port=htons(PORT);  
    /*绑定服务器的ip和服务器端口号*/
    if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)     
    {      
        std::cerr<<"Bind error:"<<strerror(errno)<<"\n\a";       
        exit(1);     
    } else{
        std::cout<<"Bind successful!\n";    
    }  
     /* 设置允许连接的最大客户端数 */     
     if(listen(sockfd,BACKLOG)==-1)     
     {    
        std::cerr<<"Listen error:"<<strerror(errno)<<"\n\a"; 
        exit(1);  
     } else{
        std::cout<<"Listening.....\n"; 
     } 
     return sockfd;
}

/*创建共享存储区*/
int shmid_create()
{    
    int shmid;     
    if((shmid = shmget(IPC_PRIVATE,SIZE_SHMADD,0777)) < 0)       
    { 
        perror("shmid error!"); 
        exit(1); 
    }
    else  
        std::cout<<"shmid success!\n";
    return shmid;
}
int main(int argc, char *argv[]) 
{   
    char shmadd_buffer[SIZE_SHMADD],buffer[SIZE];      
    sockaddr_in client_addr;  
    socklen_t sin_size;   
    pid_t ppid,pid;     
    int new_fd; 
    int shmid;
    char *shmadd;
    /***********共享内存**************/
    shmid = shmid_create();
    //映射共享内存
    shmadd = static_cast<char*>(shmat(shmid, 0, 0));
    /*****创建套接字描述符***********/ 
    int sockfd = get_sockfd();
    /*循环接收客户端*/
    while(1)
    {   
        /* 服务器阻塞,直到客户程序建立连接 */         
        sin_size=sizeof(sockaddr_in);        
        if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1)         
        { 
            std::cerr<<"Accept error:"<<strerror(errno)<<"\n\a";  
            exit(1);   
        }else{
            std::cout<<"Accept successful!\n"; 
        } 
        fd[i++] = new_fd;    
        std::cout<<"\nconnected to the cilent"<<i<<" : "<<inet_ntoa(client_addr.sin_addr)<<":"<<ntohs(client_addr.sin_port)<<"\n";
        /*把界面发送给客户端*/
        memset(buffer,0,SIZE);
        strcpy(buffer,"\n----------------------------Welcome to the talk -------------------------------\n");
        send(new_fd,buffer,SIZE,0);
        //创建子进程客户端
        ppid = fork();  
        if(ppid == 0)
        {
            //将加入的新客户发送给所有在线的客户端/
            recv(new_fd,buffer,SIZE,0);
            strcat( buffer," entered the chatroom");  
            for(i=0;i<BACKLOG;i++)
            {  
                if(fd[i]!=-1)
                {  
                    send(fd[i],buffer,strlen(buffer),0);  
                }  
            }   
            //创建子进程进行读写操作/
            pid = fork();    
            while(1)
            {
                if(pid > 0)
                {
                    //父进程用于接收信息/
                    memset(buffer,0,SIZE);
                    if((recv(new_fd,buffer,SIZE,0)) <= 0)
                    {
                        close(new_fd);
                        exit(1); 
                    }
                    memset(shmadd, 0, SIZE_SHMADD);
                    strncpy(shmadd, buffer, SIZE_SHMADD);//将缓存区的客户端信息放入共享内存里
                    std::cout<<" "<<buffer<<"\n";
                }
                if(pid == 0)
                {
                    //子进程用于发送信息/
                    sleep(1);//先执行父进程
                    if(strcmp(shmadd_buffer,shmadd) != 0)
                    {
                        strcpy(shmadd_buffer,shmadd);
                        if(new_fd  > 0)
                        {
                            if(send(new_fd,shmadd,strlen(shmadd),0) == -1)
                            {
                                perror("send");
                            }                
                            memset(shmadd, 0, SIZE_SHMADD);
                            strcpy(shmadd,shmadd_buffer);                
                        }
                    }
                }
            }
        } 
    }    
    free(buffer);
    close(new_fd);
    close(sockfd);
    return 0;
}

client.cpp:
 

#include<iostream>
#include<netinet/in.h>  
#include<sys/socket.h> 
#include<sys/types.h> 
#include<string.h>
#include<stdlib.h>
#include<netdb.h>
#include<unistd.h>
#include<signal.h>
#include<errno.h>
#include<ctime>
#define SIZE 1024

int main(int argc, char *argv[])
{
    pid_t pid;
    int sockfd,confd;
    char buffer[SIZE],buf[SIZE]; 
    sockaddr_in server_addr;
    sockaddr_in client_addr;
    hostent *host;
    short port;
    char *name;  
    //四个参数
    if(argc!=4) 
    { 
        std::cerr<<"Usage:"<<argv[0]<<" hostname \a\n"; 
        exit(1); 
    } 
       //使用hostname查询host 名字 
    if((host=gethostbyname(argv[1]))==NULL) 
    { 
        std::cerr<<"Gethostname error\n"; 
        exit(1); 
    } 
        port=atoi(argv[2]);
        name=argv[3];
       /*客户程序开始建立 sockfd描述符 */ 
    if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) 
    { 
        std::cerr<<"Socket Error:"<<strerror(errno)<<"\a\n"; 
        exit(1); 
    } else{
        std::cout<<"Socket successful!\n";
    }
        /*客户程序填充服务端的资料 */ 
    bzero(&server_addr,sizeof(server_addr)); // 初始化,置0
    server_addr.sin_family=AF_INET;          // IPV4
    server_addr.sin_port=htons(port);  // (将本机器上的short数据转化为网络上的short数据)端口号
    server_addr.sin_addr=*((struct in_addr *)host->h_addr); // IP地址
    /* 客户程序发起连接请求 */ 
    if(confd=connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) 
    { 
        std::cerr<<"Connect Error:"<<strerror(errno)<<"\a\n"; 
        exit(1); 
    }else{
        std::cout<<"Connect successful!\n";
    }
    /*将客户端的名字发送到服务器端*/
    send(sockfd,name,20,0);
     /*创建子进程,进行读写操作*/
    pid = fork();//创建子进程
     while(1)
    {
       /*父进程用于发送信息*/
           if(pid > 0)
           {       
          /*时间函数*/
           struct tm *p;
           time_t timep;
           time(&timep);
           p = localtime(&timep);
           strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", p);
           /*输出时间和客户端的名字*/
           strcat(buffer," \n\tnickname ->");
           strcat(buffer,name);
           strcat(buffer,":\n\t\t  ");
           memset(buf,0,SIZE);
           fgets(buf,SIZE,stdin);
       /*对客户端程序进行管理*/
           if(strncmp("e",buf,1)==0)
           {
             std::cout<<"The client exits the chat room!\n";
             strcat(buffer,"");
             if((send(sockfd,buffer,SIZE,0)) <= 0)
             {
               perror("error send");
             }
             close(sockfd);
             sockfd = -1;
             exit(0);
           }else 
        {
            strncat(buffer,buf,strlen(buf)-1);
            strcat(buffer,"\n");              
          if((send(sockfd,buffer,SIZE,0)) <= 0)
            {
                 perror("send");
            }
           }
        }     
        else if(pid == 0)
        {
             /*子进程用于接收信息*/
               memset(buffer,0,SIZE);
               if(sockfd > 0)
               {
             if((recv(sockfd,buffer,SIZE,0)) <= 0)
               {
                  close(sockfd);
                  exit(1);
               }
               std::cout<<buffer<<"\n";
            }
        }
    }   close(sockfd);
    return 0;    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值