?? telnet.c.txt
字號:
Linux網絡編程一步一步學-用C編寫一個telnet服務器
#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); }
#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所指的內容復制
*------------------------------------------------------
*/
void AllocateMemory(char **s, int l, char *d)
{
*s = malloc(l + 1);
bzero(*s, l + 1);
memcpy(*s, d, l);
}
/************關于本文檔*************************************************************
*filename: telnet-server.c
*purpose: 這是在Linux下用C語言寫的telnet服務器,沒有用戶名和密碼,直接以開啟服務者的身份登錄系統
*wrote by: zhoulifa(zhoulifa@163.com) 周立發(http://zhoulifa.bokee.com)
Linux愛好者 Linux知識傳播者 SOHO族 開發者 最擅長C語言
*date time:2007-01-27 17:02
*Note: 任何人可以任意復制代碼并運用這些文檔,當然包括你的商業用途
* 但請遵循GPL
*Thanks to: Google.com
*Hope:希望越來越多的人貢獻自己的力量,為科學技術發展出力
* 科技站在巨人的肩膀上進步更快!感謝有開源前輩的貢獻!
**********************************************************************************/
/*------------------------------------------------------
*--- getoption - 分析取出程序的參數
*------------------------------------------------------
*/
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}
};
/* 本程序支持如一些參數:
* --host IP地址 或者 -H IP地址
* --port 端口 或者 -P 端口
* --back 監聽數量 或者 -B 監聽數量
* --dir 服務默認目錄 或者 -D 服務默認目錄
* --log 日志存放路徑 或者 -L 日志存放路徑
* --daemon 使程序進入后臺運行模式
*/
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;
/* 獲得程序工作的參數,如 IP 、端口、監聽數、網頁根目錄、目錄存放位置等 */
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是后臺工作模式(進程ID:%d)\n",
host, port, back, dirroot, logdir, daemon_y_n?"":"不", getpid());
/* fork() 兩次處于后臺工作模式下 */
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);
}
/* 處理子進程退出以免產生僵尸進程 */
signal(SIGCHLD, SIG_IGN);
/* 創建 socket */
if ((sock_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
if (!daemon_y_n) {
prterrmsg("socket()");
} else {
wrterrmsg("socket()");
}
}
/* 設置端口快速重用 */
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()");
}
}
/* 開啟臨聽 */
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);
/* 接受新連接請求 */
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, "連接來自于: %s:%d\n",
inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
if (!daemon_y_n) {
prtinfomsg(buffer);
} else {
wrtinfomsg(buffer);
}
/* 產生一個子進程去處理請求,當前進程繼續等待新的連接到來 */
if (!fork()) {
/* 把socket連接作為標準輸入、輸出、出錯句柄來用 */
dup2(new_fd, 0);
dup2(new_fd, 1);
dup2(new_fd, 2);
/* 切換到指定目錄工作 */
chdir(dirroot);
/* 交互式執行shell */
execl("/bin/bash", "-l", "--login", "-i", "-r", "-s", (char *)NULL);
}
close(new_fd);
}
close(sock_fd);
return 0;
}
用下列命令編譯程序:
gcc -Wall telnet-server -o telnetd
啟動telnet服務:
./telnetd --daemon #以root用戶身份在23端口(即telnet默認端口服務)
或
./telnetd -P 7838 #以非root用戶身份
然后開啟一個新終端,telnet連接自己的服務器試試,如:
telnet 127.0.0.1
或
telnet 127.0.0.1 7838
不需要輸入用戶名和密碼,直接以啟動telnet服務的用戶的身份登錄系統了。
輸入系統命令體驗一下吧!
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -