码迷,mamicode.com
首页 > 其他好文 > 详细

Unix网络编程学习日记 (2)

时间:2015-02-13 13:22:09      阅读:256      评论:0      收藏:0      [点我收藏+]

标签:网络编程   unix   框架   

今天继续探索《Unix网络编程》的框架。并改善上次的程序

在第一次接触中,我将error.h头文件分出,但是发现错误检测和输出大量的存在,因此归入到common.h中。

加入了一些安全包装函数,就是对于原函数的调用并进行错误检查。

用新的函数改善了daytimecpcli,并学习服务器程序daytimetcpsrv的编写。

目录结构如下:

技术分享

各个文件的作用为:

common.h:公共头文件,包含一些常量的定义和函数的声明以及常用头文件

error.c:错误输出函数的定义

wrapsock.c:socket API 的安全封装函数的定义

wrapstdio.c:Standard I/O 的安全封装函数的定义

wrapunix.c:Unix 标准API的安全封装函数的定义

error.c见上一次的日记

下面是其它文件的内容:

common.h:

#ifndef __OUR_COMMON_HDR_H
#define __OUR_COMMON_HDR_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>
#include <errno.h>

#define MAXLINE 4096
#define SA struct sockaddr

#define LISTENQ 1024 /* 2nd argument to listen() */

/* socket wrapper functions */
int Accept(int, SA *, socklen_t *);
void Bind(int, const SA *, socklen_t);
void Connect(int, const SA *, socklen_t);
void Listen(int, int);
int Socket(int, int, int);

/* Unix wrapper functions */
ssize_t Read(int, void *, size_t);
void Write(int, void *, size_t);
void Close(int);

/* Std I/O wrapper functions */
void Fputs(const char *, FILE *);

/* Error output functions */
void err_quit(const char *fmt, ...);
void err_ret(const char *fmt, ...);
void err_sys(const char *fmt, ...);
void err_dump(const char *fmt, ...);
void err_msg(const char *fmt, ...);

#endif

wrapsock.c:

#include "common.h"

int Accept(int fd, SA *sa, socklen_t *salenptr)
{
	int n;

again:
	if ((n = accept(fd, sa, salenptr)) < 0)
	{
#ifdef EPROTO
		if (errno == EPROTO || errno == ECONNABORTED)
#else
		if (errno == ECONNABORTED)
#endif
			goto again;
		else
			err_sys("accept error");
	}
	return n;
}

void Bind(int fd, const SA *sa, socklen_t salen)
{
	if (bind(fd, sa, salen) < 0)
		err_sys("bind error");
}

void Connect(int fd, const SA *sa, socklen_t salen)
{
	if (connect(fd, sa, salen) < 0)
		err_sys("connect error");
}

void Listen(int fd, int backlog)
{
	char *ptr;

	if ((ptr = getenv("LISTENQ")) != NULL)
		backlog = atoi(ptr);

	if (listen(fd, backlog) < 0)
		err_sys("listen error");
}

int Socket(int family, int type, int protocol)
{
	int n;
	if ((n = socket(family, type, protocol)) < 0)
		err_sys("socket error");

	return n;
}

wrapunix.c:

#include "common.h"

ssize_t Read(int fd, void *ptr, size_t nbytes)
{
	ssize_t n;

	if ((n = read(fd, ptr, nbytes)) == -1)
		err_sys("read error");
	return n;
}

void Write(int fd, void *ptr, size_t nbytes)
{
	if (write(fd, ptr, nbytes) != nbytes)
		err_sys("write error");
}

void Close(int fd)
{
	if (close(fd) == -1)
		err_sys("close error");
}

wrapstdio.c

#include "common.h"

void Fputs(const char *ptr, FILE *stream)
{
	if (fputs(ptr, stream) == EOF)
		err_sys("fputs error");
}

目前为止就是这样了,慢慢用到的函数再回来添加。

用上这些函数后,可以简化程序:

daytimecpcli.c:

#include "common.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>");
	sockfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, 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]);

	Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));

	while ((n = Read(sockfd, recvline, MAXLINE)) > 0)
	{
		recvline[n] = 0;
		Fputs(recvline, stdout);
	}

	exit(0);
}

daytimetcpsrv.c:

#include "common.h"
#include <time.h>

int main(int argc, char **argv)
{
	int listenfd, connfd;
	struct sockaddr_in servaddr;
	char buff[MAXLINE];
	time_t ticks;

	listenfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(IPPORT_DAYTIME);

	Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

	Listen(listenfd, LISTENQ);

	for (;;)
	{
		connfd = Accept(listenfd, (SA *) NULL, NULL);

		ticks = time(NULL);
		snprintf(buff, sizeof(buff), "%s\r\n", ctime(&ticks));
		Write(connfd, buff, strlen(buff));

		Close(connfd);
	}
}

执行效果为:

技术分享

Unix网络编程学习日记 (2)

标签:网络编程   unix   框架   

原文地址:http://blog.csdn.net/pdcxs007/article/details/43793081

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!