A Simple Telnet Server

    以前好像用过telnet的聊天室,现在很少见有人玩这个了,基本上都用网页或者图形界面的程序登录聊天。今天简单地写了一个telnet的服务器程序。虽然代码很简短,但能支持多个人同时连接,可以扩展为一些使用的程序,例如聊天、游戏、控制等。通过特殊的控制字符,还可以让telnet输出有颜色的字符。通过按一定的帧速输出字符,可以作成视频,例如气泡熊的badapple。

 

    欢迎  telnet  xiaoxia.org  2010

 

    废话少说,上代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>

#define MAX_CONNECTIONS 100

struct connection {
	int	sockfd;
	int pos;
}conns[MAX_CONNECTIONS]={0};

char* dispstr = "\
Loading . . . .\r\n\r\n\
*************************************\r\n\
What to say? \r\n\
*************************************\r\n\
(EOF)\r\n";

static void closeconn(int i)
{
	shutdown(conns[i].sockfd, SHUT_RD);
	close(conns[i].sockfd);
	conns[i].sockfd = 0;
	printf("closeconn %d\n", i);
}

int main(int argc, char **argv)
{
	fd_set fdreads;
	struct timeval tv;
	int i, ret, displen = strlen(dispstr);
	int sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
	/* reuse the network port */
	ret = 1;
	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&ret, sizeof(ret));
	struct sockaddr_in addr = {	0 };
	addr.sin_family = PF_INET;
	addr.sin_addr.s_addr = INADDR_ANY;
	addr.sin_port = htons( 2010 );
	if ( bind( sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in) ) < 0 ) {
		perror("failed to bind socket");
		return(1);
	}
	listen( sock , 5);
	printf("telserver socket is listening.\n");

	for (;;) {
		tv.tv_sec=0;
		tv.tv_usec=1000*200;
		FD_ZERO(&fdreads);
		FD_SET(sock, &fdreads);
		for (i=0; i<MAX_CONNECTIONS; i++)
			if (conns[i].sockfd) {
				do {
					if (send(conns[i].sockfd, dispstr + conns[i].pos ++, 1, 0) <= 0 ) {
						closeconn(i);
						break;
					}
				} while (!iscntrl(dispstr[conns[i].pos]) && !isspace(dispstr[conns[i].pos]) && conns[i].pos<displen);
				if (conns[i].pos>=displen)
					closeconn(i);
			}
		ret = select( MAX_CONNECTIONS+1, &fdreads, 0, 0, &tv );
		switch (ret) {
		case -1:
			perror("select error");
			break;
		case 0:
			/* timeout */
			break;
		default:
			if (FD_ISSET(sock, &fdreads)) {
				for (i=0; i<MAX_CONNECTIONS; i++)
					if (!conns[i].sockfd)
						break;
				if (i!=MAX_CONNECTIONS) {
					conns[i].sockfd = accept(sock, 0, 0);
					conns[i].pos = 0;
					printf("openconn %d\n", i);
				}
			}
		}
	}

	return 0;
}



A Simple Telnet Server》有8个想法

  1. whitefirer

    干嘛不多线程呢?不过用了select方式。。要是这样的话,不知要没有做压力测试,连接数多少?

    回复

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据