专栏首页醉梦轩Linux上C语言写的简易telnet客户端

Linux上C语言写的简易telnet客户端

telnet.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>  
#include <netinet/in.h> 
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <stdarg.h>

#define ERR_EXIT(m, ...) \  
    do { \  
        fprintf(stderr, m"\n", ##__VA_ARGS__); \  
        log(m"\n", ##__VA_ARGS__); \
        exit(EXIT_FAILURE); \  
    } while (0) 
#define MAX_BUFF_LEN 1024

void log(const char *fmt, ...)
{
    char buffer[MAX_BUFF_LEN] = {0};
    va_list args;
    time_t timep;
    time(&timep);
    struct tm *p = gmtime(&timep);
    FILE* fp = fopen("telnet.log", "a+");
    if(fp){
        snprintf(buffer, MAX_BUFF_LEN, "[%.4d-%.2d-%.2d %.2d:%.2d:%.2d][%d]", (1900+p->tm_year),(1+p->tm_mon), p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, getpid());
        va_start(args, fmt);
        vsnprintf(buffer + strlen(buffer), MAX_BUFF_LEN - strlen(buffer) - 1, fmt, args);
        va_end(args);
        fwrite(buffer, strlen(buffer), 1, fp);
        fclose(fp);
    }
}

ssize_t      /* Write "n" bytes to a descriptor. */
writen(int fd, const void *vptr, size_t n){
    size_t  nleft;
    ssize_t  nwritten;
    const char *ptr;
    ptr = vptr;
    nleft = n;
    while (nleft > 0) {
        if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
            if (nwritten < 0 && errno == EINTR)
                nwritten = 0;  /* and call write() again */
            else
                return(-1);   /* error */
        }
        nleft -= nwritten;
        ptr   += nwritten;
    }
    return(n);
}

int main(int argc,char **argv){
    if(argc < 3){
        fprintf(stderr, "Usage: %s ServerIPAddress ServerPort\n",argv[0]);
        return 0;
    }

    fd_set rset;
    FD_ZERO(&rset);
    int sock = socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;    //internet协议族
    struct hostent *h = gethostbyname(argv[1]);
    server_addr.sin_addr = *((struct in_addr *)h->h_addr);
    server_addr.sin_port = htons(atoi(argv[2]));
    if(connect(sock,(struct sockaddr*)&server_addr, sizeof(struct sockaddr_in)) < 0){
        ERR_EXIT("connect to %s:%s failed", argv[1], argv[2]);
    }

    fprintf(stdout, "% 9d\n", getpid());
    fflush(stdout);

    int nready;  
    int maxfd;  
    int fd_stdin = fileno(stdin);
    int fd_stdout = fileno(stdout);
    if (fd_stdin > sock)  
        maxfd = fd_stdin;  
    else  
        maxfd = sock;  
    char sendbuf[1024*4] = {0};  
    char recvbuf[1024*4] = {0};  

    while (1){  
        FD_SET(fd_stdin, &rset);  
        FD_SET(sock, &rset);  
        nready = select(maxfd + 1, &rset, NULL, NULL, NULL); //select返回表示检测到可读事件  
        if (nready == -1) ERR_EXIT("select error");  
        if (nready == 0) continue;  
        if (FD_ISSET(sock, &rset)){  
            int ret = read(sock, recvbuf, sizeof(recvbuf)); //按行读取  
            if (ret == -1) ERR_EXIT("read from socket error");  
            else if (ret  == 0) ERR_EXIT("server close");  //服务器关闭  

            writen(fd_stdout, recvbuf, ret);
            memset(recvbuf, 0, sizeof(recvbuf));  
        }  
        if (FD_ISSET(fd_stdin, &rset)){  
            int ret = read(fd_stdin, sendbuf, sizeof(sendbuf));
            if(ret > 0) {
                writen(sock, sendbuf, ret);  
                memset(sendbuf, 0, sizeof(sendbuf));
            }else{
                ERR_EXIT("read from stdin error");                
            }
        }  
    }  
    close(sock);  
    exit(0);
}

编译方法:

gcc -o telnet telnet.c

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • UIAutomator2.0和AccessibilityService实现分析

    UiAutomator是Android 4.1以上提供的一个UI自动化测试工具,4.3升级到了UiAutomator2.0,实现方式也从UiTestAutoma...

    drunkdream
  • Win10上误删Linux子系统的解决方法

    最近在折腾Win10里的WSL的时候,不小心把WSL的目录删除了,然后无论如何再也装不上去。运行bash命令会报以下错误:

    drunkdream
  • 编译可用的Android模拟器ranchu内核

    drunkdream
  • Linux下进程间通讯方式 - UNIX Domain Socket

    Linux下进程通讯方式有很多,比较典型的有套接字,平时比较常用的套接字是基于TCP/IP协议的,适用于两台不同主机上两个进程间通信, 通信之前需要指定IP地址...

    程序手艺人
  • 27:级数求和

    27:级数求和 总时间限制: 1000ms 内存限制: 65536kB描述 已知:Sn= 1+1/2+1/3+…+1/n。显然对于任意一个整数K,当n足够大的...

    attack
  • 蓝桥杯-2019第十届蓝桥杯B组C++迷宫

    下图给出了一个迷宫的平面图,其中标记为1 的为障碍,标记为0 的为可 以通行的地方。 010000 000100 001001 110000 迷宫的入口为左上角...

    Debug客栈
  • 洛谷P1138 第k小整数

    题目描述 现有n个正整数,n≤10000,要求出这n个正整数中的第k个最小整数(相同大小的整数只计算一次),k≤1000,正整数均小于30000。 输入输出格式...

    attack
  • 16:最长单词2

    16:最长单词2 总时间限制: 1000ms 内存限制: 65536kB描述 一个以'.'结尾的简单英文句子,单词之间用空格分隔,没有缩写形式和其它特殊形式...

    attack
  • 服务器线程并发和进程并发

    Aichen
  • P3368 【模板】树状数组 2(树状数组维护差分序列)

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N、M,...

    attack

扫码关注云+社区

领取腾讯云代金券