最近在看《UNIX网络编程》(简称unp)和《Linux程序设计》,对于unp中第一个获取服务器时间的例子,实践起来总是有点头痛的,因为作者将声明全部包含在了unp.h里,导致后面编写代码会对这个头文件造成依赖,而学习不到调用了相应功能之后,应该包含哪些确切的头文件。
再者,我下载了unp.h之后,头文件包含再次产生了其他的依赖缺失,因此便参考了《Linux程序设计》中socket一章的入门例子的头文件包含,并且编译中仍然找不到的包含或者是宏定义在unp.h中搜索并粘贴进来,从而不需要再包含类似unp.h之类的自定义头文件。
以下代码在root权限下运行,因为使用的端口号13对于非root用户可能会无权访问。
unp原书中服务器获取机器时间送回客户端,但我在运行中,字符串保存到buffer区的函数snprintf()总是造成了内存错误而中断,所以本着入门的目的,改为了复制一句话到buffer中。
/*client.c*/ #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <sys/un.h> #include <unistd.h> #include <stdlib.h> #include <netinet/in.h> #define MAXLINE 4096 #define PORT 13 #define SA struct sockaddr int main(int argc, char *argv[]) { int sockfd, n; ]; struct sockaddr_in servaddr; ) { fprintf(stderr, "usage: client <IP>\n"); exit(); } )) < ) { fprintf(stderr, "socket error\n"); exit(); } bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); ], &servaddr.sin_addr) <= ) { fprintf(stderr, ]); exit(); } ) { fprintf(stderr, "connect error\n"); exit(); } ) { recvline[n] = ; if (fputs(recvline, stdout) == EOF) { fprintf(stderr, "fputs error\n"); exit(); } } ) { fprintf(stderr, "read error\n"); exit(); } exit(); }
/*server.c*/ #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <sys/un.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <netinet/in.h> #define MAXLINE 4096 #define LISTENQ 1024 #define PORT 13 #define SA struct sockaddr int main(int argc, char *argv[]) { int listenfd, connfd; struct sockaddr_in servaddr; ]; time_t t; listenfd = socket(AF_INET, SOCK_STREAM, ); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(PORT); bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); listen(listenfd, LISTENQ); ) { connfd = accept(listenfd, (SA *)NULL, NULL); /* write something to buff[]*/ strcpy(buff, "this is a message\n"); write(connfd, buff, strlen(buff)); close(connfd); } exit(); }
编译文件:
$ gcc client.c -o client $ gcc server.c -o server
在一个窗口中运行服务器:
$ ./server
在另一个窗口运行客户端,从而显示出一句话"this is a message":
$ ./client 127.0.0.1