• Telnet模拟系统(Linux c)


    3章详细设计和实现

    3.1相关技术

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

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

      3)对文件的读写操作

      4popen调用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 ",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] = '';

                    /* 用户名鉴定 */

                    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("用户登录成功! ");

    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("客户端已断开连接! ");

      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] = ''; //去除最后一个输入的确认

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

        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("连接已断开 ");          

    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="123";
    
     
    
    #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[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("客户端已断开连接!
    ");
    
      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" );    
    
        }/*
    
    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 0;     
    
    }
    
     
    
     
    
    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, 0, BUF_SIZE );
    
        memset( &server_addr, 0, sizeof(server_addr) );
    
        memset( &client_addr, 0, sizeof(server_addr) );
    
     
    
        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" );
    
     
    
    printf("telnet服务器已开启……
    ");
    
        while ( 1 ) {
    
        if ( (connfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_size)) < 0 ) //响应客户端请求
    
                printf( "accept failed" );
    
            printf( "Server accept a client: ip = %s
    ",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] = '';
    
     
    
                    /* 用户名鉴定 */
    
                    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("用户登录成功!
    ");
    
    recv_type = COMMAND;  //设置标志为命令模式
    
                        }                
    
                    }
    
    /* 命令模式 */
    
    else if( recv_type == COMMAND ) {
    
    command(connfd,buffer);   
    
    puts("客户端输入的命令为:");
    
    puts(buffer);                 
    
                    }
    
                }
    
                close( sockfd );
    
                close( connfd );
    
                exit ( 0 );
    
            }
    
            else
    
                close( connfd );
    
        }
    
        return 0;
    
    }
    
     

    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, 0, sizeof(input_buf));
    
    memset(recv_buf, 0, sizeof(recv_buf));
    
        
    
    fgets( input_buf, BUF_SIZE, stdin ); //获取用户输入
    
        input_buf[strlen(input_buf) - 1] = ''; //去除最后一个输入的确认
    
     
    
        /* 向服务器发送消息 */
    
        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("连接已断开
    ");          
    
    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 != 3 ) {
    
            printf( "输入格式为: ./c  [ip] [port]
    " );
    
            exit ( 1 );
    
        }
    
     
    
        memset( &serv_addr, 0, sizeof(struct sockaddr_in) );//置零
    
     
    
        serv_addr.sin_family = AF_INET;
    
        serv_addr.sin_port = htons( atoi(argv[2]) );
    
        inet_aton( argv[1], &serv_addr.sin_addr );
    
     
    
        if ( serv_addr.sin_port == 0 ||serv_addr.sin_addr.s_addr == 0 ) {
    
            fprintf( stderr, "输入格式为: ./c  [ip] [port]
    " );
    
            exit ( 1 );
    
        }
    
     
    
        connfd = socket( AF_INET, SOCK_STREAM, 0 );  //创建socket
    
        if ( connfd < 0 )
    
            printf( "socket failed" );
    
     
    
        if ( connect(connfd, (struct sockaddr *)&serv_addr,sizeof(struct sockaddr)) < 0 ) //连接服务器
    
        {    
    
            printf( "connect failed" );
    
        exit(0);
    
        }
    
    printf("请输入用户名:");
    
    /*输入操作*/
    
        if ( send_recv( connfd, 'u' ) == TRUE )
    
    {
    
       printf("请输入密码:");
    
           if ( send_recv( connfd,'p' )== TRUE )
    
    {
    
    while(1)
    
    {
    
    printf("guest@ubantu:");
    
    if ( send_recv( connfd, 'c' )== FALSE )
    
    {
    
        close( connfd );
    
            exit(0);
    
    }
    
    }
    
    }
    
    }
    
        close( connfd );
    
        return 0;
    
    }
    
     
  • 相关阅读:
    2018-8-10-win10-uwp-win2d-使用-Path-绘制界面
    2018-8-10-win10-uwp-win2d-使用-Path-绘制界面
    PHP money_format() 函数
    PHP metaphone() 函数
    PHP md5_file() 函数
    PHP md5() 函数
    PHP ltrim() 函数
    查看统计信息
    CF960F Pathwalks_权值线段树_LIS
    hdu 5691 Sitting in line 状压动归
  • 原文地址:https://www.cnblogs.com/emmm/p/10318183.html
Copyright © 2020-2023  润新知