linux_echo_客户端

来源:互联网 发布:淘宝商家微淘怎么设置 编辑:程序博客网 时间:2024/05/23 18:43

题目

1. 功能

-----------------------------------------------------------------------------------------------------------------------------------

Ø 1实现一个并发echo服务器程序,它(接收端)将接收到的字符串进行转换处理后返回给发送端;有多个发送端同时存在(最多同时有n个有效客户端,超出的客户端无法与echo服务器通讯);

Ø 字符串的处理包括:直接返回、全部转换为大写、全部转换为小写;处理方式应可以配置,配置方式包括全局(缺省)及每“发送-接收对(xmit/recv peer)”的。配置转换时,不应该影响正在处理的字符串;

Ø 为模拟处理过程的延时,接收端中每个“字符”转换添加200ms的延迟

Ø 接收端中需统计其处理字符的数量,并且给外部提供命令形式的查询手段

Ø 具备必要的例外处理,如内存不足、通讯失败、连接断开等;

Ø 具备可移植性,能够在各种处理器架构上运行,如X86/RISC32-bits/64-bits

-----------------------------------------------------------------------------------------

2. 程序结构(应用专业方向)

------------------------------------------------------------------------------------------------------------------------------

Ø 以有链接client-server方式实现echo程序

Ø 存在多个clientclientserver在同一个系统中,它们之间采用domain socketnetlink socket相连;client之间没有关联

Ø client是一个程序的多个实例,而server只允许运行一个实例

------------------------------------------------------------------------------------------

3. 程序结构(内核专业方向)

--------------------------------------------------------------------------------------------------------------------------------

Ø 内核模块作为接收端,而发送端是用户空间的应用程序;

Ø 内核模块可动态加载与卸载

Ø 使用procexport统计值及当前配置

Ø 创建内核线程,作为内核中的server,与用户通信可采用netlink socket或其它可用的方式;

Ø 使用proc配置echo处理转换方式

------------------------------------------------------------------------------------------------------------------------------------

4. 功能界面

------------------------------------------------------------------------------------------------------------------------------------

Ø 客户端程序命名为client,以参数来确定是与用户空间中的server通信(-u)还是与内核中的server通信(-k)。客户端运行后的大致界面如下:

root@ubuntu:~#client –u

Client ID is 250.

CLIENT> aBcde

ECHO: aBcde

CLIENT> A B C

ECHO: A B C

CLIENT> quit

root@ubuntu:~#

Ø 用户空间中的server程序命名为server,用户空间中的server运行后的大致界面如下:

root@ubuntu:~#server

SERVER> mode 250 lower

SERVER> mode 0 upper      ///0表示进行全局(缺省)配置

SERVER> mode 250 normal

SERVER> show

Server info:

Global mode: upper

Characters: 85

Clients: 2

SERVER> quit

root@ubuntu:~#

Ø 内核空间中的server程序命名为server.ko,内核空间中的server运行后,通过向proc写入类似“mode 250 upper”来配置server的转换处理方式,通过proc进行读操作,来显示server的信息

Ø ClientServer无法建立连接时,Client中显示以下信息后退出:

Unable to establish a connection with the server!

clientserver的连接断开时,Client中显示以下信息后退出:

Disconnected from the server!

Server中显示类似以下信息:

Disconnected from the client 250

——END——


客户端

main.c

/* * Copyright(C) 2016 Ruijie Network. All rights reserved. *//* * usrspace_main.c * Original Author: suntianyu@ruijie.com.cn,  2016-8-7 * * echo UserSpace client * * History * */   #include "send_msg.h"char   cmd[2];/* signal function */void signal_handle(){    char send_buff[4] = "quit";    if (strcmp(cmd,"-u") == 0) {        printf("\nDisconnected from the server!\n");        quit();     }         /*  kernel client */    if (strcmp(cmd,"-k") == 0) {        netlink_send(send_buff);        printf("\nDisconnected from the server!\n");        netlink_socket_exit();    }     exit(0);    return;}/* kserver  */void link2kernel_server(void);/* userver  */void link2usr_server(void);/* main  */int main(int argc, char* argv[]){    signal(SIGINT, signal_handle);    signal(SIGQUIT, signal_handle);    printf("Client PID is %d.\n",getpid());    if (argc != 2) {        printf("input command error!\n");        printf("please input formant: ./client -u/-k\n");        return 1;    }   else {        memcpy(cmd,argv[1],2);        /*  user  client  */        if (strcmp(argv[1],"-u") == 0) {            link2usr_server();        }         /*  kernel client */        if (strcmp(argv[1],"-k") == 0) {            link2kernel_server();        }  else {           printf("please input formant add -u/-k\n");           return 1;        }    }    return 0;}/* quit  */void quit(void){     close(client_sock);    exit(0);}/* userver  */void link2usr_server(void) {        int ret,i;    char check_array[4] = "quit";    char msg[100] = {"\0"};     struct sockaddr_un client_address;    client_sock = socket(AF_UNIX,SOCK_STREAM,0);     if (client_sock == -1) {        printf("socket() error\n");        return;    }       client_address.sun_family = AF_UNIX;    strcpy(client_address.sun_path,ECHO_ADDR);    ret = connect(client_sock,(struct sockaddr *)&client_address,sizeof(client_address));    if (ret == -1) {        perror("connect failed");        exit(1);    }        recv(client_sock,msg,5,0);    printf("Client ID is %s\n",msg);    while (1) {          memset(msg,0,sizeof(msg));        printf("\nCLIENT> ");        fgets(msg, 100, stdin);                       for (i=0;i < 4;i++) {            if (msg[i] != check_array[i]) {                break;               }        }        if (i == 4) {            printf("\nDisconnected from the server!\n");            quit();        }                send(client_sock,msg,strlen(msg),0);        recv(client_sock,msg,strlen(msg),0);                              printf("\nECHO: %s",msg);    }    return;}/* kserver  */void link2kernel_server(void) {    if (netlink_socket_init() != 0) {        netlink_socket_exit();        return;    }    if (connect_server() == ERROR) {        netlink_socket_exit();        return;    }            while (1) {        printf("CLIENT> ");        fgets(send_buff, MAXMSGLEN, stdin);               if (netlink_send(send_buff) == ERROR ) {            printf("Disconnected from the server!\n");            break;        };        if (recvmsg(netlink_socket, &netlink_msg, 0) < 0) {            printf("Disconnected from the server!\n");            break;        }        strcpy(recv_buff, NLMSG_DATA(nlh));                printf("\nECHO: %s\n", recv_buff);    }    netlink_socket_exit();}

netlink_send_msg.h

/* * Copyright(C) 2016 Ruijie Network. All rights reserved. *//* * send_msg.h * Original Author: suntianyu@ruijie.com.cn,  2016-8-7 * * echo User client * * History * */   #ifndef _SEND_MSG_H_   #define _SEND_MSG_H_#include <stdio.h>#include <stdlib.h>  #include <string.h> #include <sys/types.h>  #include <sys/socket.h>  #include <asm/types.h>  #include <linux/socket.h>  #include <linux/netlink.h>   #include <unistd.h>   #include <sys/stat.h>        /* For mode constants */#include <time.h>#include <sys/time.h>#include <errno.h>#include <linux/socket.h>#include <sys/socket.h>#include <stddef.h>  #include <sys/stat.h>  #include <sys/un.h> #include <signal.h>#include <stddef.h>#include <errno.h> #define  USER_NETLINK_CMD    25  #define  MAXMSGLEN           1024  #define  MAX_PAYLOAD         1024#define  ERROR               -1#define  NETLINK_ECHO        31#define  ECHO_ADDR           "/tmp/echo_address"struct sockaddr_nl netlink_saddr, netlink_daddr;struct nlmsghdr *nlh ;struct msghdr netlink_msg;struct iovec netlink_iov;char   send_buff[MAXMSGLEN];char   recv_buff[MAXMSGLEN];int    netlink_socket;int    client_sock;                   /* init netlink */int    netlink_socket_init(void);/* exit netlink */int    netlink_socket_exit(void);/* netlink connect */int    netlink_connect_server(void);/* netlink send */int    netlink_send(char * send_buff);/* quit */void   quit(void);#endif /* _SEND_MSG_H_ */ 


netlink_send_msg.c
/* * Copyright(C) 2016 Ruijie Network. All rights reserved. *//* * senf_msg.c * Original Author: suntianyu@ruijie.com.cn,  2016-8-7 * * echo User client * * History * */   #include "send_msg.h"/* judge function */int judge_input(char *buf){    int i;    char check_array[4];    char buff[4] = "quit";    if (buf == NULL) {        return 0;    }    memcpy(check_array,buf,4);    for (i=0;i < 4;i++) {        if (buff[i] != check_array[i]) {            break;        }    }    if (i == 4) {        return ERROR;    }      return 0;}/* configure netlink */void configure_netlink_address(struct sockaddr_nl * socket_addr, int dst_pid){    memset(socket_addr, 0, sizeof(struct sockaddr_nl));    socket_addr->nl_family = AF_NETLINK;    socket_addr->nl_pad = 0;    socket_addr->nl_pid = dst_pid;    socket_addr->nl_groups = 0;}/* netlink init */int netlink_socket_init(void)  {      int ret;    netlink_socket = socket(PF_NETLINK, SOCK_RAW,NETLINK_ECHO);    if (netlink_socket == ERROR) {        printf("Disconnected from the server!\n");        return ERROR;    }    configure_netlink_address(&netlink_saddr, getpid());    configure_netlink_address(&netlink_daddr, 0);    ret = bind(netlink_socket, (struct sockaddr*)&netlink_saddr, sizeof(struct sockaddr));    if (ret != 0) {        printf("Disconnected from the server!\n");        return ERROR;    }    nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));    if (nlh == NULL) {        return ERROR;    }    return 0;}  /* netlink send */  int netlink_send(char * send_buf)  {      int ret;    ret = 0;    if (send_buf == NULL) {        return 0;    }    if (judge_input(send_buf) == ERROR) {         nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);        nlh->nlmsg_pid = getpid();        nlh->nlmsg_flags = 0;        strcpy(NLMSG_DATA(nlh), "quit");        memset(&netlink_msg, 0 ,sizeof(netlink_msg));        netlink_iov.iov_base = (void *)nlh;        netlink_iov.iov_len = nlh->nlmsg_len;        netlink_msg.msg_name = (void *)&netlink_daddr;        netlink_msg.msg_namelen = sizeof(netlink_daddr);        netlink_msg.msg_iov = &netlink_iov;        netlink_msg.msg_iovlen = 1;        ret = sendmsg(netlink_socket, &netlink_msg, 0);         return ERROR;    }     nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);    nlh->nlmsg_pid = getpid();    nlh->nlmsg_flags = 0;    strcpy(NLMSG_DATA(nlh), send_buf);    memset(&netlink_msg, 0 ,sizeof(netlink_msg));    netlink_iov.iov_base = (void *)nlh;    netlink_iov.iov_len = nlh->nlmsg_len;    netlink_msg.msg_name = (void *)&netlink_daddr;    netlink_msg.msg_namelen = sizeof(netlink_daddr);    netlink_msg.msg_iov = &netlink_iov;    netlink_msg.msg_iovlen = 1;    ret = sendmsg(netlink_socket, &netlink_msg, 0);       return ret;}  /* connect  */int connect_server(void){    int i;    char buff[10];    char send_buff[MAXMSGLEN] = "suntianyu";    if (netlink_send(send_buff) == ERROR ) {        printf("Unable to establish a connection with the server!\n");        goto error;    };    if (recvmsg(netlink_socket, &netlink_msg, 0) < 0) {        printf("Unable to establish a connection with the server!\n");        goto error;    }    memcpy(buff,(char *)NLMSG_DATA(nlh),10);    for (i=0;i < 9;i++) {        if (buff[i] != send_buff[i]) {            printf("\nUnable to establish a connection with the server!\n");              goto error;        }    }    return 0;  error:      return ERROR;  }/* exit  */int netlink_socket_exit(void)  {       free(nlh);    close(netlink_socket);      return 0;  }  




0 0