第3章详细设计和实现

3.1相关技术

  1)TCP编程,主要包括socket()函数、bind()函数、listen()函数、recv()函数、send()函数以及客户端的connect()函数。

  2)C语言中对结构体的操作,和对字符串的比较

  3)对文件的读写操作

  4)popen调用shell

3.2开发工具和运行环境

  本系统在ubantu 16.4 LTS环境下开发,所用的工具为vi编辑器和gedit编辑器,以及gcc编译工具。

 

3.3主要功能的源码

3.3.1服务器端socket的建立

if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )  //创建socket

printf( "socket failed" );

/* 设置端口快速重用*/

optval = 1;

if ( setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&optval, sizeof(int)) < 0 )

printf( "setsockopt failed" );

server_addr.sin_family = AF_INET;

server_addr.sin_port = htons( PORT );

server_addr.sin_addr.s_addr = htonl( INADDR_ANY );

if ( bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) < 0 ) //绑定ip和端口号

printf( "bind failed" );

if ( listen(sockfd, MAX_LISTEN) < 0 ) //建立监听

printf( "listen failed" );

3.3.2对客户端的发送信息进行处理

while ( 1 ) {

if ( (connfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_size)) < 0 ) //响应客户端请求

printf( "accept failed" );

printf( "Server accept a client: ip = %s\n",inet_ntoa(client_addr.sin_addr) ); //打印客户端ip

/* 创建子进程处理客户端请求 */

if ( (pid = fork()) == 0 ) {

while ( 1 ) {

/* 接受客户端信息 */

if ( (recv_bits = recv(connfd, buffer, BUF_SIZE, 0)) < 0 )

printf( "recv failed" );

/* 去除最后一个字符 */

buffer[recv_bits - 1] = '\0';

/* 用户名鉴定 */

if ( recv_type == USERNAME ) {

if ( strcmp(name, buffer) != 0 ) {

if ( send(connfd, error_user,strlen(error_user), 0) < 0 )

printf( "send failed" );

break;

}else{

if ( send(connfd, correct_user,strlen(correct_user), 0) < 0 )

printf( "send failed" );

}

printf("%s正在登录:",buffer);

recv_type = PASSWORD;  //设置标志为密码鉴定模式

}

/* 密码鉴定 */

else if ( recv_type == PASSWORD ) {

if ( strcmp(passwd, buffer) != 0 ) { //验证密码

if ( send(connfd, error_password,strlen(error_password), 0) < 0 )

printf( "send failed" );

} else {

if ( send(connfd, success_login, strlen(success_login), 0) < 0 )

printf( "send failed" );

printf("用户登录成功!\n");

recv_type = COMMAND;  //设置标志为命令模式

}

}

/* 命令模式 */

else if( recv_type == COMMAND ) {

command(connfd,buffer);

puts("客户端输入的命令为:");

puts(buffer);

}

}

close( sockfd );

close( connfd );

exit ( 0 );

}

else

close( connfd );

}

 3.3.3 执行命令函数

int command(int connfd,char*command)

{

/*

*  作用:通过popen调用shell执行command命令

*  connfd: 客户端标识

*  command: 命令字符串

*/

FILE *fstream = NULL;

char buff[1024];

memset(buff, 0, sizeof(buff));

if ( strcmp(exit_command, command) == 0 ) { //退出

if ( send(connfd, exit_command,strlen(exit_command), 0) < 0 )

printf( "send failed" );

printf("客户端已断开连接!\n");

return 0;

}

if(NULL == (fstream = popen(command,"r")))

{

fprintf(stderr,"execute command failed: %s",strerror(errno));

return -1;

}

while(NULL != fgets(buff, sizeof(buff), fstream))

{

//printf("%s",buff);

if ( send(connfd, buff,strlen(buff), 0) < 0 ) //将命令执行结果发送至客户端

printf( "send failed" );

}

pclose(fstream);

return 0;

}

3.3.4客户端发送与接受信息

int send_recv( int connfd,char flag )

{

/*

*  作用:客户端与服务器端信息的处理

*  connfd: 服务器端标识

*  flag: 输入类比标识

*/

char input_buf[ BUF_SIZE ]; //定义字符串存放输入信息

char recv_buf[ BUF_SIZE ]; //定义字符串存放服务器端返回信息

memset(input_buf, 0, sizeof(input_buf));

memset(recv_buf, 0, sizeof(recv_buf));

fgets( input_buf, BUF_SIZE, stdin ); //获取用户输入

input_buf[strlen(input_buf) - 1] = '\0'; //去除最后一个输入的确认

/* 向服务器发送消息 */

if ( send(connfd, input_buf, BUF_SIZE, 0) < 0 )

printf( "send failed" );

/* 从服务器接受消息 */

if ( recv(connfd, recv_buf, BUF_SIZE, 0) < 0 )

printf( "recv failed" );

/* 用户名处理 */

if ( flag == 'u' ) {

if ( strcmp(recv_buf, error_user) == 0 ) {  //用户名错误

puts( error_user );

return FALSE;

}

}

/* 密码处理 */

else if ( flag == 'p' ) {

if ( strcmp(recv_buf, error_password) == 0 )

{  puts( error_password );  //密码错误

return FALSE;

}

}

/* 命令处理 */

else if( flag == 'c' )

{

if ( strcmp(recv_buf, exit_command) == 0 ) {  //退出

printf("连接已断开\n");

return FALSE;

}

puts(recv_buf); //命令结果输出

}

return TRUE;

}

第7章 附录

7.1服务器端

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <assert.h>

#include <errno.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#define PORT         3333

//用户名和密码

char *name="twain";

char *passwd="";

#define MAX_LISTEN    10

#define BUF_SIZE     1024

#define USERNAME   0

#define PASSWORD   1   

#define COMMAND    2

//登录过程状态标识

char *error_user = "error user name";

char *error_password = "error password";

char *correct_user = "correct user";

char *success_login = "correct password";

char *exit_command = "exit";

char *exit_tip="退出连接!";

/*

* 介绍:服务器端

* 功能:

*    1.接受客户端的登录请求并验证

*    2.接受客户端的命令在本地执行并返回执行结果

*/

int command(int connfd,char*command)

{    

    /*

     *  作用:执行command命令

     *  connfd: 客户端标识

     *  command: 命令字符串

    */

    FILE *fstream = NULL;      

    char buff[];    

    memset(buff, , sizeof(buff));   

if ( strcmp(exit_command, command) ==  ) { //退出

        if ( send(connfd, exit_command,strlen(exit_command), ) <  )

          printf( "send failed" );

printf("客户端已断开连接!\n");

  return ;

    }

    if(NULL == (fstream = popen(command,"r")))      

    {     

        fprintf(stderr,"execute command failed: %s",strerror(errno));      

        return -;      

    }   

    while(NULL != fgets(buff, sizeof(buff), fstream))

    {  

        //printf("%s",buff);  

if ( send(connfd, buff,strlen(buff), ) <  ) //将命令执行结果发送至客户端

            printf( "send failed" );    

    }/*

if(NULL != fgets(buff, sizeof(buff), fstream))

    {  

        //printf("%s",buff);  

if ( send(connfd, buff,strlen(buff), 0) < 0 )

            printf( "send failed" );    

    }else{

if ( send(connfd, "..",sizeof("buff"), 0) < 0 )

            printf( "send failed" );

}*/

    pclose(fstream);    

    return ;     

}

int main( int argc, char *argv[] )

{

    int    sockfd, connfd;

    int optval;

    int recv_type = USERNAME;  //默认为USERNAME,即用户名输入模式

    int client_size;

    int recv_bits;  

    char buffer[ BUF_SIZE ];

    pid_t pid;

    struct sockaddr_in client_addr, server_addr;

    client_size = sizeof( struct sockaddr_in );

    /* 初始化各变量为零 */

    memset( buffer, , BUF_SIZE );

    memset( &server_addr, , sizeof(server_addr) );

    memset( &client_addr, , sizeof(server_addr) );

    if ( (sockfd = socket(AF_INET, SOCK_STREAM, )) <  )  //创建socket

        printf( "socket failed" );

    /* 设置端口快速重用*/

    optval = ;

    if ( setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&optval, sizeof(int)) <  )

        printf( "setsockopt failed" );

    server_addr.sin_family = AF_INET;

    server_addr.sin_port = htons( PORT );

    server_addr.sin_addr.s_addr = htonl( INADDR_ANY );

   if ( bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) <  ) //绑定ip和端口号

        printf( "bind failed" );

    if ( listen(sockfd, MAX_LISTEN) <  ) //建立监听

        printf( "listen failed" );

printf("telnet服务器已开启……\n");

    while (  ) {

    if ( (connfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_size)) <  ) //响应客户端请求

            printf( "accept failed" );

        printf( "Server accept a client: ip = %s\n",inet_ntoa(client_addr.sin_addr) ); //打印客户端ip

        /* 创建子进程处理客户端请求 */

        if ( (pid = fork()) ==  ) {

            while (  ) {

                /* 接受客户端信息 */

                if ( (recv_bits = recv(connfd, buffer, BUF_SIZE, )) <  )

                    printf( "recv failed" );

                /* 去除最后一个字符 */

                buffer[recv_bits - ] = '\0';

                /* 用户名鉴定 */

                if ( recv_type == USERNAME ) {

                    if ( strcmp(name, buffer) !=  ) {

                     if ( send(connfd, error_user,strlen(error_user), ) <  )

                            printf( "send failed" );

break;

                    }else{

if ( send(connfd, correct_user,strlen(correct_user), ) <  )

                            printf( "send failed" );

}

printf("%s正在登录:",buffer);

                        recv_type = PASSWORD;  //设置标志为密码鉴定模式

                }

                /* 密码鉴定 */

                else if ( recv_type == PASSWORD ) {

                    if ( strcmp(passwd, buffer) !=  ) { //验证密码

                     if ( send(connfd, error_password,strlen(error_password), ) <  )

                            printf( "send failed" );

                    } else {

                       if ( send(connfd, success_login, strlen(success_login), ) <  )

                            printf( "send failed" );

printf("用户登录成功!\n");

recv_type = COMMAND;  //设置标志为命令模式

                    }                

                }

/* 命令模式 */

else if( recv_type == COMMAND ) {

command(connfd,buffer);   

puts("客户端输入的命令为:");

puts(buffer);                 

                }

            }

            close( sockfd );

            close( connfd );

            exit (  );

        }

        else

            close( connfd );

    }

    return ;

}

7.2客户端

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <assert.h>

#include <errno.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#define TRUE        1

#define FALSE       -1

#define BUF_SIZE     1024

//登录过程状态标识

char *error_user = "error user name";

char *error_password = "error password";

char *correct_user = "correct user";

char *success_login = "correct password";

char *exit_command = "exit";

char *exit_tip="退出连接!";

/*

* 介绍:客户端

* 功能:

*    1.登录服务器端

*    2.登录后在服务器端对文件进行操作

*/

int send_recv( int connfd,char flag )

{

 /*

     *  作用:客户端与服务器端信息的处理

     *  connfd: 服务器端标识

 *  flag: 输入类比标识

    */

    char input_buf[ BUF_SIZE ]; //定义字符串存放输入信息

    char recv_buf[ BUF_SIZE ]; //定义字符串存放服务器端返回信息

memset(input_buf, , sizeof(input_buf));

memset(recv_buf, , sizeof(recv_buf));

fgets( input_buf, BUF_SIZE, stdin ); //获取用户输入

    input_buf[strlen(input_buf) - ] = '\0'; //去除最后一个输入的确认

    /* 向服务器发送消息 */

    if ( send(connfd, input_buf, BUF_SIZE, ) <  )

        printf( "send failed" );

    /* 从服务器接受消息 */

    if ( recv(connfd, recv_buf, BUF_SIZE, ) <  )

        printf( "recv failed" );

/* 用户名处理 */

    if ( flag == 'u' ) {

        if ( strcmp(recv_buf, error_user) ==  ) {  //用户名错误

            puts( error_user );

            return FALSE;

        }

    }

/* 密码处理 */

    else if ( flag == 'p' ) {

        if ( strcmp(recv_buf, error_password) ==  )

          {  puts( error_password );  //密码错误

 return FALSE;

}

    }

/* 命令处理 */

else if( flag == 'c' )

{

if ( strcmp(recv_buf, exit_command) ==  ) {  //退出

printf("连接已断开\n");          

return FALSE;

        }

puts(recv_buf); //命令结果输出

}

    return TRUE;

}

int main( int argc, char *argv[] )

{

    int    connfd;

    int serv_port;

    char recv_buf[ BUF_SIZE ];

    struct sockaddr_in    serv_addr;

    if ( argc !=  ) {

        printf( "输入格式为: ./c  [ip] [port]\n" );

        exit (  );

    }

    memset( &serv_addr, , sizeof(struct sockaddr_in) );//置零

    serv_addr.sin_family = AF_INET;

    serv_addr.sin_port = htons( atoi(argv[]) );

    inet_aton( argv[], &serv_addr.sin_addr );

    if ( serv_addr.sin_port ==  ||serv_addr.sin_addr.s_addr ==  ) {

        fprintf( stderr, "输入格式为: ./c  [ip] [port]\n" );

        exit (  );

    }

    connfd = socket( AF_INET, SOCK_STREAM,  );  //创建socket

    if ( connfd <  )

        printf( "socket failed" );

    if ( connect(connfd, (struct sockaddr *)&serv_addr,sizeof(struct sockaddr)) <  ) //连接服务器

    {    

        printf( "connect failed" );

    exit();

    }

printf("请输入用户名:");

/*输入操作*/

    if ( send_recv( connfd, 'u' ) == TRUE )

{

   printf("请输入密码:");

       if ( send_recv( connfd,'p' )== TRUE )

{

while()

{

printf("guest@ubantu:");

if ( send_recv( connfd, 'c' )== FALSE )

{

    close( connfd );

        exit();

}

}

}

}

    close( connfd );

    return ;

}

Telnet模拟系统(Linux c)的更多相关文章

  1. Windows使用Telnet连接Linux服务器初探(待实践)

    在Windows下可以适用Telnet连接Linux服务器,但是前提是在Linux下需要安装Tlenet-Server.还要开启防火的23端口.搞定之后就可以用telnet IP进行连接. 但是,我发 ...

  2. Linux学习之七-配置Telnet连接Linux服务器

    配置Telnet连接Linux服务器 通过telnet可以从windows平台访问linux 服务器 ,实现和ssh 客户端一样的效果,区别在于通过ssh连接更安全. 检查Linux系统中是否安装了t ...

  3. 设置用root用户telnet到linux系统

    默认情况下,ROOT用户不能以telnet方式连接Linux操作系统,而且也是不安全的.但从技术上来讲,是可以实现的. #mv /etc/securetty /etc/securetty.bak 保存 ...

  4. 如何开启telnet服务LINUX&Windows

    一.LINUX centos 1.Linux安装telnet包 # yum install telnet* # rpm -qa |grep telnet telnet-server-0.17-47.e ...

  5. linux中脚本权限问题以及win下使用telnet测试linux端口

    一个脚本叫up,执行脚本报错如下: -bash: ./up: Permission denied 解决: chmod +rx up 在执行,OK了. /************************ ...

  6. linux telnet命令参数及用法详解--telnet连接远程终端命令

    功能说明:远端登入. 语 法:telnet [-8acdEfFKLrx][-b<主机alias.html' target='_blank'>别名>][-e<脱离字符>][ ...

  7. Linux 下Telnet 服务安装

    Linux 下Telnet 服务安装 注:以下所有命令均在root用户下执行. 命令测试在Linxu版本6.x下完成,部分命令不适用Linux 7.0以上 1.简介 默认情况下Linux只安装了Tel ...

  8. Windows 如何使用telnet管理虚拟机Linux

    Linux远程登录的工具很多,如putty,SecureCRT…… 其实借助Windows的telnet工具就可以在命令提示符轻松的登录到Linux系统进行操作了. 虽然telnet很简单,但还是要进 ...

  9. Linux(十)___iptables防火墙

    一.防火墙的作用 三.防火墙的分类 三.iptables基本语法: 表: 常用filter,nat用于地址映射转换. 配置文件: /etc/sysconfig/iptables 过滤表信息 . 查看i ...

随机推荐

  1. Oracle EBS 查看请求执行情况

    SELECT s.* FROM fnd_concurrent_requests r, v$session v, v$sql s WHERE r.oracle_session_id = v.audsid ...

  2. mongodb存储引擎

    存储引擎(Storage Engine)是MongoDB的核心组件,负责管理数据如何存储在硬盘(Disk)和内存(Memory)上.从MongoDB 3.2 版本开始,MongoDB 支持多数据存储引 ...

  3. 要提高SQL查询效率where语句条件的先后次序应如何写

    我们要做到不但会写SQL,还要做到写出性能优良的SQL语句. (1)选择最有效率的表名顺序(只在基于规则的优化器中有效): Oracle的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句 ...

  4. 使用ASP.Net WebAPI构建REST服务——客户端

    原文的链接:http://www.cnblogs.com/TianFang/p/3724449.html WebAPI是标准的Http协议,支持Http协议的客户端(如浏览器)都可以访问.但是,有的时 ...

  5. 转:eclipse的快捷键

    22 21 Eclipse中10个最有用的快捷键组合  一个Eclipse骨灰级开发者总结了他认为最有用但又不太为人所知的快捷键组合.通过这些组合可以更加容易的浏览源代码,使得整体的开发效率和质量得到 ...

  6. 给UIScrollView添加category实现UIScrollView的轮播效果

    给UIScrollView添加category实现UIScrollView的轮播效果 大家都知道,要给category添加属性是必须通过runtime来实现的,本教程中给UIScrollView添加c ...

  7. ELK搭建实时日志分析平台之二Logstash和Kibana搭建

    本文书接前回<ELK搭建实时日志分析平台之一ElasticSearch> 文:铁乐与猫 四.安装Logstash logstash是一个数据分析软件,主要目的是分析log日志. 1)下载和 ...

  8. 深入 Java 调试体系: 第 1 部分,初探JPDA 体系

    JPDA(Java Platform Debugger Architecture)是 Java 平台调试体系结构的缩写,通过 JPDA 提供的 API,开发人员可以方便灵活的搭建 Java 调试应用程 ...

  9. 1.1 What Is This Book About(这本书是关于什么的)

    CHAPTER 1 Preliminaries(预备知识) 1.1 What Is This Book About?(这本书是关于什么的) 这本书关心的是如何用Python对数据进行处理和清洗等操作. ...

  10. mycat结合双主复制实现读写分离模式

    简介:应用程序仅需要连接mycat,后端服务器的读写分离由mycat进行控制,后端服务器数据的同步由MySQL主从同步进行控制. 本次实验环境架构图 服务器主机规划 主机名 IP  功能 备注 lin ...