linux_echo_客户端
来源:互联网 发布:淘宝商家微淘怎么设置 编辑:程序博客网 时间:2024/05/23 18:43
题目
1. 功能
-----------------------------------------------------------------------------------------------------------------------------------
Ø 1、实现一个并发的echo服务器程序,它(接收端)将接收到的字符串进行转换处理后返回给发送端;有多个发送端同时存在(最多同时有n个有效客户端,超出的客户端无法与echo服务器通讯);
Ø 字符串的处理包括:直接返回、全部转换为大写、全部转换为小写;处理方式应可以配置,配置方式包括全局(缺省)及每“发送-接收对(xmit/recv peer)”的。配置转换时,不应该影响正在处理的字符串;
Ø 为模拟处理过程的延时,接收端中每个“字符”转换添加200ms的延迟;
Ø 接收端中需统计其处理字符的数量,并且给外部提供命令形式的查询手段
Ø 具备必要的例外处理,如内存不足、通讯失败、连接断开等;
Ø 具备可移植性,能够在各种处理器架构上运行,如X86/RISC、32-bits/64-bits;
-----------------------------------------------------------------------------------------
2. 程序结构(应用专业方向)
------------------------------------------------------------------------------------------------------------------------------
Ø 以有链接的client-server方式实现echo程序
Ø 存在多个client,client与server在同一个系统中,它们之间采用domain socket或netlink socket相连;client之间没有关联
Ø client是一个程序的多个实例,而server只允许运行一个实例
------------------------------------------------------------------------------------------
3. 程序结构(内核专业方向)
--------------------------------------------------------------------------------------------------------------------------------
Ø 内核模块作为接收端,而发送端是用户空间的应用程序;
Ø 内核模块可动态加载与卸载
Ø 使用proc来export统计值及当前配置
Ø 创建内核线程,作为内核中的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的信息。
Ø 当Client与Server无法建立连接时,Client中显示以下信息后退出:
Unable to establish a connection with the server!
当client与server的连接断开时,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_ */
/* * 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; }
- linux_echo_客户端
- linux_echo_内核态服务器
- linux_echo_用户态服务器
- 客户端
- 客户端
- 客户端
- 客户端
- 客户端
- 客户端
- 客户端
- 客户端
- 客户端
- 客户端
- 【JS】【客户端】客户端JavaScript
- 胖客户端、瘦客户端与智能客户端
- 胖客户端、瘦客户端和富客户端
- 客户端配置文件
- 智能客户端
- [JS]JavaScript Offset
- SwiftyJSON源码分析
- Storm与Kafka集成
- Android7.0 PowerManagerService亮灭屏分析(三)
- 打包上架错误
- linux_echo_客户端
- java邮件提醒实现
- System Bar (Status Bar Navigation Bar)
- 在windows上部署phpwind
- 第六天(高婷我爱你)
- Android开发进阶—View的事件体系
- android系统移植(一) 总述
- MAC地址,ARP协议,以太网
- 最全 jdbc从入门到精通