最近开始学习unix网络编程,开篇第一个程序daytimetcpcli.c编译运行成功,就花费了很多心思,把问题汇总出来,供各位参考。
FreeBsd unix 系统构建的vmware虚拟机,之前对FreeBsd也是小白,虽说也玩过linux,对网络通信这些设置啊还是不熟。
书中源代码如下:
#include
"../lib/unp.h"
#include "../lib/error.c"
int
main(int argc, char **argv)
{
int sockfd, n;
char recvline[MAXLINE + 1];
struct sockaddr_inservaddr;
if (argc != 2)
err_quit("usage: a.out <IPaddress>");
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
err_sys("socket error");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(13);/* daytime server */
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
err_quit("inet_pton error for %s", argv[1]);
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
err_sys("connect error");
while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
recvline[n] = 0;/* null terminate */
if (fputs(recvline, stdout) == EOF)
err_sys("fputs error");
}
if (n < 0)
err_sys("read error");
exit(0);
}
FreeBsd 安装成功后,telnet 和ftp这些服务,要自己开启,在/etc/inetd.conf,用ee命令开启,可以直接编辑,
要保存必须用root权限,esc后aa保存。ps -ef | grep inetd 查看PID号,kill 后,用 inetd -wW重
新开启,新设置生效。
编辑其实就是去掉相应行的“#”注释。
#ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l
#ftp stream tcp6 nowait root /usr/libexec/ftpd ftpd -l
#telnet stream tcp nowait root /usr/libexec/telnetd telnetd
#telnet stream tcp6 nowait root /usr/libexec/telnetd telnetd
言归正传,cc daytimetcpcli.c,生成a.out, 运行./a.out 127.0.0.1
总是提示connect error: Connection refused。
用sockstat 查看服务器运行的端口,有21,23这些常见的端口。
百度说应该没有开daytime服务端口。看freebsd手册,说这些服务是内置默认启动的。
再回到网络编程书中,看后面的代码解释,知道是connect执行失败,再分析后关键点在
htons(13)这个函数,
其中13是服务端口号,把13改成其他端口看看,然后改成21,发现执行成功。
虽然执行成功,但是不是书中的daytime字串,心里还是有些遗憾。现在至少能证明
服务器没有问题,应该是配置还有些没有设置正确。继续百度。
随后在基维百科中看到daytime协议的解释:
DAYTIME协议(英语:DAYTIME protocol)是一个在RFC 867内定义的网络传输协议。
主机可以用TCP或UDP端口 13连接支持DAYTIME协议的服务器。
服务器会以ASCII字符传回当时日期及时间。格式类似:星期,月 日,年 时区。
它也用作测试电脑网络的联通性,现在测试网络的方法已经转为用ping或traceroute。
DAYTIME协议在inetd上
在Linux、FreeBSD,或其他类UNIX操作系统中,DAYTIME时间服务器是在inetd中内置。通常DAYTIME协议服务是默认关闭的,或是在/etc/inetd.conf文件中加上以下数据以打开服务:
daytime stream tcp nowait root internal daytime stream tcp6 nowait root internal daytime dgram udp wait root internal daytime dgram udp6 wait root internal
看了上面的解释,再把daytime服务开启,重新启动inetd,一切OK
看到inetd.conf里面有很多#开头的行,应该是很多服务都要手工开启。
书中第一个例子总算完美执行成功,这样的开始才让人欣喜。小白继续前进