pdcxs007的专栏

今天开始拜读《Unix网络编程》。找到的源代码在Linux下有各种问题,最后决定还是自己从头写比较好。

从第一个时间服务程序开始学习。今天先看一下主要的头文件的作用。

在common.h中(参照 unp.h 自己写的,包含常用头文件和一些常量定义,用着方便),有以下的头文件:

sys/types.h

此头文件是系统类型的定义,,如:int8_t int16_t int32_t int64_t等等

sys/socket.h

这是socket的接口,在其中引入bits/socket.h,其中定义了各种常量。

netinet/in.h

定义了各种地址结构体和常量。

arpa/inet.h

定义了地址转换的函数。

其它的头文件是常用头文件。还有一些常数定义以及结构体的简称。以后会随时添加。

在error.c和error.h中,声明和定义了常用的错误输出。

目录结构为下图所示:

以下是源程序:

daytimecpcli.c:

#include "common.h"#include "error.h"int main(int argc, char **argv){int sockfd, n;char recvline[MAXLINE + 1];struct sockaddr_in servaddr;if (argc != 2)err_quit("usage: ./daytimecpcli.c <IP address>");if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)err_sys("socket error");memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(IPPORT_DAYTIME);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;if (fputs(recvline, stdout) == EOF)err_sys("fputs error");}if (n < 0)err_sys("read error");exit(0);}common.h:

#ifndef __COMMON_H#define __COMMON_H#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#define MAXLINE 4096#define SA struct sockaddr#endiferror.h:

#ifndef __MYERROR_H#define __MYERROR_H#include <stdio.h>#include <stdlib.h>void err_ret(const char *fmt, …);void err_sys(const char *fmt, …);void err_dump(const char *fmt, …);void err_msg(const char *fmt, …);void err_quit(const char *fmt, …);#endiferror.c:

#include <errno.h> /* for definition of errno */#include <stdarg.h> /* ANSI C header file */#include "error.h"#include "common.h"static void err_doit(int, const char *, va_list);void err_ret(const char *fmt, …){va_list ap;va_start(ap, fmt);err_doit(1, fmt, ap);va_end(ap);return;}void err_sys(const char *fmt, …){va_list ap;va_start(ap, fmt);err_doit(1, fmt, ap);va_end(ap);exit(1);}void err_dump(const char *fmt, …){va_list ap;va_start(ap, fmt);err_doit(1, fmt, ap);va_end(ap);abort();exit(1);}void err_quit(const char *fmt, …){va_list ap;va_start(ap, fmt);err_doit(0, fmt, ap);va_end(ap);exit(1);}void err_msg(const char *fmt, …){va_list ap;va_start(ap, fmt);err_doit(0, fmt, ap);va_end(ap);return;}static void err_doit(int errnoflag, const char *fmt, va_list ap){int errno_save;char buf[MAXLINE];errno_save = errno;vsprintf(buf, fmt, ap);if (errnoflag)sprintf(buf+strlen(buf), ": %s", strerror(errno_save));strcat(buf, "\n");fflush(stdout);fputs(buf, stderr);fflush(stderr);return;}我将error.c制作成了名为liberr.a的静态库,为以后连接方便做准备。所以,sock目录下的Makefile内容如下:

all: liberr.aliberr.a: liberr.oar rv liberr.a liberr.oliberr.o: error.c error.h common.hgcc error.c -c -o liberr.oclean:rm -rf *.o *.aintro目录下的Makefile内容如下:

targets = daytimecpclicc = gccINCLUDES = -I"../sock/"LIBS = -L"../sock/"all: $(targets)daytimecpcli: daytimecpcli.c ../sock/liberr.a$(cc) -o daytimecpcli daytimecpcli.c $(LIBS) -lerr $(INCLUDES)../sock/liberr.a: ../sock/error.c ../sock/error.h ../sock/common.hcd ../sock && makeclean:rm -rf $(targets) *.o在打开书上的程序daytimetcpsrv时,程序执行效果如下:

你写PPT时,阿拉斯加的鳕鱼正跃出水面,

pdcxs007的专栏

相关文章:

你感兴趣的文章:

标签云: