- 論壇徽章:
- 0
|
Linux網(wǎng)絡(luò)編程一步一步學(xué)-用C自己編寫(xiě)一個(gè)telnet服務(wù)器
服務(wù)器源代碼如下:
- #include <stdarg.h>
- #include <errno.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string.h>
- #include <time.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <dirent.h>
- #include <errno.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <resolv.h>
- #include <arpa/inet.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <getopt.h>
- #define DEFAULTIP "127.0.0.1"
- #define DEFAULTPORT "23"
- #define DEFAULTBACK "10"
- #define DEFAULTDIR "/tmp"
- #define DEFAULTLOG "/tmp/telnet-server.log"
- void prterrmsg(char *msg);
- #define prterrmsg(msg) { perror(msg); abort(); }
- void wrterrmsg(char *msg);
- #define wrterrmsg(msg) { fputs(msg, logfp); fputs(strerror(errno), logfp);fflush(logfp); abort(); }
- void prtinfomsg(char *msg);
- #define prtinfomsg(msg) { fputs(msg, stdout); }
- void wrtinfomsg(char *msg);
- #define wrtinfomsg(msg) { fputs(msg, logfp); fflush(logfp);}
- #define MAXBUF 1024
- char buffer[MAXBUF + 1];
- char *host = 0;
- char *port = 0;
- char *back = 0;
- char *dirroot = 0;
- char *logdir = 0;
- unsigned char daemon_y_n = 0;
- FILE *logfp;
- #define MAXPATH 150
- /*------------------------------------------------------
- *--- AllocateMemory - 分配空間并把d所指的內(nèi)容復(fù)制
- *------------------------------------------------------
- */
- void AllocateMemory(char **s, int l, char *d)
- {
- *s = malloc(l + 1);
- bzero(*s, l + 1);
- memcpy(*s, d, l);
- }
- /************關(guān)于本文檔*************************************************************
- *filename: telnet-server.c
- *purpose: 這是在Linux下用C語(yǔ)言寫(xiě)的telnet服務(wù)器,沒(méi)有用戶名和密碼,直接以開(kāi)啟服務(wù)者的身份登錄系統(tǒng)
- *wrote by: zhoulifa(zhoulifa@163.com) 周立發(fā)(http://zhoulifa.bokee.com)
- Linux愛(ài)好者 Linux知識(shí)傳播者 SOHO族 開(kāi)發(fā)者 最擅長(zhǎng)C語(yǔ)言
- *date time:2007-01-27 17:02
- *Note: 任何人可以任意復(fù)制代碼并運(yùn)用這些文檔,當(dāng)然包括你的商業(yè)用途
- * 但請(qǐng)遵循GPL
- *Thanks to: Google.com
- *Hope:希望越來(lái)越多的人貢獻(xiàn)自己的力量,為科學(xué)技術(shù)發(fā)展出力
- * 科技站在巨人的肩膀上進(jìn)步更快!感謝有開(kāi)源前輩的貢獻(xiàn)!
- **********************************************************************************/
- /*------------------------------------------------------
- *--- getoption - 分析取出程序的參數(shù)
- *------------------------------------------------------
- */
- void getoption(int argc, char **argv)
- {
- int c, len;
- char *p = 0;
- opterr = 0;
- while (1) {
- int option_index = 0;
- static struct option long_options[] = {
- {"host", 1, 0, 0},
- {"port", 1, 0, 0},
- {"back", 1, 0, 0},
- {"dir", 1, 0, 0},
- {"log", 1, 0, 0},
- {"daemon", 0, 0, 0},
- {0, 0, 0, 0}
- };
- /* 本程序支持如一些參數(shù):
- * --host IP地址 或者 -H IP地址
- * --port 端口 或者 -P 端口
- * --back 監(jiān)聽(tīng)數(shù)量 或者 -B 監(jiān)聽(tīng)數(shù)量
- * --dir 服務(wù)默認(rèn)目錄 或者 -D 服務(wù)默認(rèn)目錄
- * --log 日志存放路徑 或者 -L 日志存放路徑
- * --daemon 使程序進(jìn)入后臺(tái)運(yùn)行模式
- */
- c = getopt_long(argc, argv, "H:P:B:D:L",
- long_options, &option_index);
- if (c == -1 || c == '?')
- break;
- if(optarg) len = strlen(optarg);
- else len = 0;
- if ((!c && !(strcasecmp(long_options[option_index].name, "host")))
- || c == 'H')
- p = host = malloc(len + 1);
- else if ((!c
- &&
- !(strcasecmp(long_options[option_index].name, "port")))
- || c == 'P')
- p = port = malloc(len + 1);
- else if ((!c
- &&
- !(strcasecmp(long_options[option_index].name, "back")))
- || c == 'B')
- p = back = malloc(len + 1);
- else if ((!c
- && !(strcasecmp(long_options[option_index].name, "dir")))
- || c == 'D')
- p = dirroot = malloc(len + 1);
- else if ((!c
- && !(strcasecmp(long_options[option_index].name, "log")))
- || c == 'L')
- p = logdir = malloc(len + 1);
- else if ((!c
- &&
- !(strcasecmp
- (long_options[option_index].name, "daemon")))) {
- daemon_y_n = 1;
- continue;
- }
- else
- break;
- bzero(p, len + 1);
- memcpy(p, optarg, len);
- }
- }
- int main(int argc, char **argv)
- {
- struct sockaddr_in addr;
- int sock_fd, addrlen;
- /* 獲得程序工作的參數(shù),如 IP 、端口、監(jiān)聽(tīng)數(shù)、網(wǎng)頁(yè)根目錄、目錄存放位置等 */
- getoption(argc, argv);
- if (!host) {
- addrlen = strlen(DEFAULTIP);
- AllocateMemory(&host, addrlen, DEFAULTIP);
- }
- if (!port) {
- addrlen = strlen(DEFAULTPORT);
- AllocateMemory(&port, addrlen, DEFAULTPORT);
- }
- if (!back) {
- addrlen = strlen(DEFAULTBACK);
- AllocateMemory(&back, addrlen, DEFAULTBACK);
- }
- if (!dirroot) {
- addrlen = strlen(DEFAULTDIR);
- AllocateMemory(&dirroot, addrlen, DEFAULTDIR);
- }
- if (!logdir) {
- addrlen = strlen(DEFAULTLOG);
- AllocateMemory(&logdir, addrlen, DEFAULTLOG);
- }
- printf
- ("host=%s port=%s back=%s dirroot=%s logdir=%s %s是后臺(tái)工作模式(進(jìn)程ID:%d)\n",
- host, port, back, dirroot, logdir, daemon_y_n?"":"不", getpid());
- /* fork() 兩次處于后臺(tái)工作模式下 */
- if (daemon_y_n) {
- if (fork())
- exit(0);
- if (fork())
- exit(0);
- close(0), close(1), close(2);
- logfp = fopen(logdir, "a+");
- if (!logfp)
- exit(0);
- }
- /* 處理子進(jìn)程退出以免產(chǎn)生僵尸進(jìn)程 */
- signal(SIGCHLD, SIG_IGN);
- /* 創(chuàng)建 socket */
- if ((sock_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
- if (!daemon_y_n) {
- prterrmsg("socket()");
- } else {
- wrterrmsg("socket()");
- }
- }
- /* 設(shè)置端口快速重用 */
- addrlen = 1;
- setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &addrlen,
- sizeof(addrlen));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(atoi(port));
- addr.sin_addr.s_addr = inet_addr(host);
- addrlen = sizeof(struct sockaddr_in);
- /* 綁定地址、端口等信息 */
- if (bind(sock_fd, (struct sockaddr *) &addr, addrlen) < 0) {
- if (!daemon_y_n) {
- prterrmsg("bind()");
- } else {
- wrterrmsg("bind()");
- }
- }
- /* 開(kāi)啟臨聽(tīng) */
- if (listen(sock_fd, atoi(back)) < 0) {
- if (!daemon_y_n) {
- prterrmsg("listen()");
- } else {
- wrterrmsg("listen()");
- }
- }
- while (1) {
- int new_fd;
- addrlen = sizeof(struct sockaddr_in);
- /* 接受新連接請(qǐng)求 */
- new_fd = accept(sock_fd, (struct sockaddr *) &addr, &addrlen);
- if (new_fd < 0) {
- if (!daemon_y_n) {
- prterrmsg("accept()");
- } else {
- wrterrmsg("accept()");
- }
- break;
- }
- bzero(buffer, MAXBUF + 1);
- sprintf(buffer, "連接來(lái)自于: %s:%d\n",
- inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
- if (!daemon_y_n) {
- prtinfomsg(buffer);
- } else {
- wrtinfomsg(buffer);
- }
- /* 產(chǎn)生一個(gè)子進(jìn)程去處理請(qǐng)求,當(dāng)前進(jìn)程繼續(xù)等待新的連接到來(lái) */
- if (!fork()) {
- /* 把socket連接作為標(biāo)準(zhǔn)輸入、輸出、出錯(cuò)句柄來(lái)用 */
- dup2(new_fd, 0);
- dup2(new_fd, 1);
- dup2(new_fd, 2);
- /* 切換到指定目錄工作 */
- chdir(dirroot);
- /* 交互式執(zhí)行shell */
- execl("/bin/bash", "-l", "--login", "-i", "-r", "-s", (char *)NULL);
- }
- close(new_fd);
- }
- close(sock_fd);
- return 0;
- }
復(fù)制代碼
用下列命令編譯程序:
gcc -Wall telnet-server -o telnetd
啟動(dòng)telnet服務(wù):
./telnetd --daemon #以root用戶身份在23端口(即telnet默認(rèn)端口服務(wù))
或
./telnetd -P 7838 #以非root用戶身份
然后開(kāi)啟一個(gè)新終端,telnet連接自己的服務(wù)器試試,如:
或
不需要輸入用戶名和密碼,直接以啟動(dòng)telnet服務(wù)的用戶的身份登錄系統(tǒng)了。
輸入系統(tǒng)命令體驗(yàn)一下吧! |
|