Linux中简单服务器(+-*/%)的与客户端的实现

头文件 utili.h

#pragma once 
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>

#define BUFFER_SIZE 256
#define TCP 0
#define UDP 1
#define LISTW_QUEUE_SIZE 5

typedef enum {QUIT,ADD,SUB,MUL,DIV,MOD}OPER_ENUM;

typedef struct oper_st
{
    int op1;
    int op2;
    OPER_ENUM op;
}oper_st;

int start_up(char *ip,short port , int mode)
{
    int sockfd;
    if(mode == TCP)
    {
      sockfd  = socket(AF_INET,SOCK_STREAM,0);
    }
    else if(mode == UDP)
    {
      sockfd = socket(AF_INET,SOCK_DGRAM,0);
    }
    else
    {
        printf("mode errror,mode is must tcp or udp.....\n");
        return -1;
    }
    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_port = htons(port);
    address.sin_addr.s_addr = inet_addr(ip);

    socklen_t addrlen = sizeof(struct sockaddr);
    int yes = 1;
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes , sizeof(int));
    int ret = bind(sockfd,(struct sockaddr*)&address,addrlen);
    if(ret == -1)
    {
        perror("bind");
        return -1;
    }
    if(mode == TCP)
    {
        ret =  listen(sockfd,LISTW_QUEUE_SIZE);
        if(ret == -1)
        {
            perror("listen");
            return -1;
        }
    }
    return sockfd;
}


ser.cpp  

服务器启动是需要两个参数 :ip地址与端口号 ,服务器菜单控制 1:显示已经连接的客户端数 2:显示已经连接的客户端ip地址与端口号 0:退出

/********************* Creation Date:2018-05-06  09:13*******************/
#include"utili.h"
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
#include<list>
typedef struct client_node
{
    char ip[16];
    short port;
}client_node;
typedef struct client_info
{   
    int client_num;
    list<client_node*> lt;
}client_info;

static int client_num;
void process_handler(int sockConn);
void* Server_Seach(void *arg)
{   
    client_info *info = (client_info*)arg;
    int select = 1;
    while(1)
    {
        printf("*********************************\n");
        printf("*[1]Search Client Num.          *\n");
        printf("*[2]Search Clint Info.          *\n");
        printf("*[0]Quit System.                *\n");
        printf("*********************************\n");
        printf("Input Choice:>");
        scanf("%d",&select);
        switch(select)
        {
            case 1:
                printf("client number:>%d\n",info->client_num);
                break;
            case 2:
                {
                    list<client_node *>::iterator it = (info->lt).begin();
                    while(it != (info->lt).end())
                    {
                        cout<<"****************************"<<endl;
                        cout<<"*client ip:>"<<(*it)->ip<<endl;
                        cout<<"*client port:>"<<(*it)->port<<endl;
                        cout<<"****************************"<<endl;
                        ++it;
                    }
                }
                break;
            case 0:
                printf("This server is quit....\n");
                exit(1);
                break;;
                exit(1);
        }
    }
}

int main(int argc , char *argv[])
{   
    client_info client;
    client.client_num = 0;
    pthread_t tid;//创建后台处理程序,采用线程,数据可以共享
    pthread_create(&tid,NULL,Server_Seach,&client);
    int sockSer = start_up(argv[1],atoi(argv[2]),TCP);//调用套接字启动函数
    if(sockSer == -1)
    {
        perror("socket");
        return -1;
    }
    
    oper_st oper;//定义一个操作数
    
    int sockConn;
    socklen_t len = sizeof(struct sockaddr);
    struct sockaddr_in addrCli;
    while(1)
    { 
        sockConn = accept(sockSer,(struct sockaddr*)&addrCli,&len);
        if(sockConn == -1)
        {
           printf("Accept Client connect Error.\n");
            continue;
        }
        else
        {
            client.client_num ++;
            client_node *s = (client_node*)malloc(sizeof(client_node));
            strcpy(s->ip,inet_ntoa(addrCli.sin_addr));
            s->port = ntohs(addrCli.sin_port);
            client.lt.push_back(s);
            printf("\n");
            printf("<==============Client================>\n");
            printf("<===========ip = %s========>\n",inet_ntoa(addrCli.sin_addr));
            printf("<===========port= %d>=============>\n",ntohs(addrCli.sin_port));
            printf("<====================================>\n");
        }
        pid_t pid = fork();
        if(pid == 0)//子进程
        {
            process_handler(sockConn);
        }
        else if(pid > 0)//父进程
        {
           // int status;
           // wait(&status);
           close(sockConn);
        }
        else
        {
            perror("fock process");
        }
    }
    
    close(sockSer);
    return 0;
}

void process_handler(int sockConn)
{   int result;
    int ret_byte_size;
    oper_st oper;
    while(1)
    {
        
        ret_byte_size = recv(sockConn,&oper,sizeof(oper),0);
        if(ret_byte_size < 0 )
        {
            perror("redv data error.");
            continue;
        }
        if(oper.op == ADD)
            result = oper.op1 + oper.op2;
        else if(oper.op == SUB)
            result = oper.op1 - oper.op2;
        else if(oper.op == MUL)
            result = oper.op1 * oper.op2;
        else if(oper.op == DIV)
            result = oper.op1 / oper.op2;
        else if(oper.op == MOD)
            result = oper.op1 % oper.op2;
        else if(oper.op == QUIT)
        {
            printf("Client Quit.\n");
            break;
        }
        ret_byte_size = send(sockConn , &result ,sizeof(result),0);
        if(ret_byte_size < 0)
        {
            perror("send data error.");
                continue;
        }
    }
    close(sockConn);

}


cli.c

/********************* Creation Date:2018-05-05  13:00*******************/
#include"utili.h"

int main(int arge , char*argv[])
{
    int sockCli = socket(AF_INET , SOCK_STREAM,0);
    if(sockCli == -1)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in addrSer;
    addrSer.sin_family = AF_INET;
    addrSer.sin_port = htons(atoi(argv[2]));
    addrSer.sin_addr.s_addr = inet_addr(argv[1]);

    socklen_t len = sizeof(struct sockaddr);
    int ret = connect(sockCli,(struct sockaddr*)&addrSer,len);
    if(ret == -1)
    {
        perror("connect");
        close(sockCli);
        exit(1);
    }
    else
    {
        printf("Connect is success.\n");
    }
    
    oper_st oper;
    char cmd[5];
    int result;
    int ret_byte_size;
    while(1)
    {
        printf("please chose cmd[add,sub,mul,div,mod,quit]\n");
        printf("Input cmd:\n");
        scanf("%s",cmd);
        //if(strcmp(cmd ,"quit") == 0)
          //      break;
        if(strcmp(cmd,"add") == 0)
            oper.op = ADD;
        else if(strcmp(cmd,"sub") == 0)
            oper.op = SUB;
        else if(strcmp(cmd,"mul") == 0)
            oper.op = MUL;
        else if(strcmp(cmd,"div") == 0)
            oper.op = DIV;
        else if(strcmp(cmd,"mod") == 0)
            oper.op = MOD;
        else if(strcmp(cmd,"quit") == 0)
        {
            oper.op = QUIT;
            send(sockCli,&oper,sizeof(oper),0);
            break;
        }

        printf("Please input op1 and op2:>");
        scanf("%d %d",&oper.op1,&oper.op2);
      ret_byte_size =  send(sockCli , &oper ,sizeof(oper),0);
        if(ret_byte_size < 0)
        {
            perror("send data errro.");
            continue;
        }
       ret_byte_size = recv(sockCli ,&result , sizeof(result),0);
        if(ret_byte_size < 0)
        {
            perror("recv data error.");
        }
        printf("result = %d\n",result);
    }
    close(sockCli);
    printf("System Quit ....\n");
    return 0;
}


客户端启动也需要两个参数:ip地址与端口号必须要和服务器一直。

猜你喜欢

转载自blog.csdn.net/zzb2019/article/details/80258169