您的位置:首页 > 理论基础 > 计算机网络

TCP 回射程序(处理子进程的SIGCHLD信号)

2016-11-14 11:46 417 查看
客户端的代码;

/*************************************************************************
> File Name: tcpcli.c
> Author: mhsheng
> Mail:981065720@qq.com
> Created Time: Wed 09 Nov 2016 10:55:40 AM CST
************************************************************************/

// c standard head file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>

// system i/o head file
#include <unistd.h>

// socket head file
#include <netinet/in.h>

#define MAXLINE		1024
#define LISTENQ		5
#define SERV_PORT	9066

void
err_quit(const char *str_err)
{
fprintf(stderr, "%s\n", str_err);
exit(-1);
}

void
err_sys(const char *str_err)
{
fprintf(stderr, "%s\n", str_err);
exit(-1);
}

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

return sockfd;
}

void
Connect(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)
{
if (connect(sockfd, myaddr, addrlen) < 0)
err_sys("connect error");
}

void
Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)
{
if (bind(sockfd, myaddr, addrlen) < 0)
err_sys("bind error");
}

void
Listen(int sockfd, int backlog)
{
if (listen(sockfd, backlog) < 0)
err_sys("listen error");
}

int
Accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)
{
int connfd;

connfd = accept(sockfd, cliaddr, addrlen);
if (connfd < 0)
err_sys("accept error");

return connfd;
}

void
Close(int sockfd)
{
if (close(sockfd) < 0)
err_sys("close error");
}

//////////////////////////////////////////////////////////////////////////
// Writen begin
//

ssize_t
writen(int fd, const void *vptr, size_t n)
{
size_t		nleft;
ssize_t		nwritten;
const char	*ptr;

ptr		= vptr;
nleft	= n;
while (nleft > 0) {
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
if (nwritten < 0 && errno == EINTR)
nwritten = 0;		/* and call write() again */
else
return (-1);
}

nleft	-= nwritten;
ptr		+= nwritten;
}

return (n);
}

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

//
// Writen end
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// Readline begin
//

static int	read_cnt;
static char	*read_ptr;
static char	read_buf[MAXLINE];

static	ssize_t
my_read(int fd, char *ptr)
{
if (read_cnt <= 0) {
for ( ; ; ) {
if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
if (errno == EINTR)
continue;
return -1;
} else if (read_cnt == 0)
return 0;

read_ptr = read_buf;
break;
}
}

read_cnt--;
*ptr = *read_ptr++;
return 1;
}

ssize_t
readline(int fd, void *vptr, size_t maxlen)
{
ssize_t	n;
ssize_t	rc;
char	c;
char	*ptr;

ptr = vptr;
for (n=1; n<maxlen; n++) {
if ( (rc = my_read(fd, &c)) == 1) {
*ptr++ = c;
if (c == '\n')
break;
} else if (rc == 0) {
*ptr = 0;		/* EOF, n - 1 bytes were read */
return n-1;
} else {
return -1;
}
}

*ptr = 0;
return n;
}

ssize_t
Readline(int fd, void *ptr, size_t maxlen)
{
ssize_t	n;

if ( (n = readline(fd, ptr, maxlen)) < 0)
err_sys("readline error");
return n;
}

//
// Readline end
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// wrapstdio begin
//

// Fgets begin
char *
Fgets(char *ptr, int n, FILE *stream)
{
char *rptr;

if ( (rptr = fgets(ptr, n, stream)) == NULL && ferror(stream))
err_sys("fgets error");

return rptr;
}
// Fgets end

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

//
// wrapstdio end
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// str_echo begin
//

void
str_echo(int sockfd)
{
char	buf[MAXLINE];
ssize_t	n;

for ( ; ; ) {
// 从套接字读取数据
while ( (n = read(sockfd, buf, MAXLINE)) > 0)
// 将读取的数据发送给客户端
Writen(sockfd, buf, n);

if (n < 0 && errno == EINTR)
continue;
else if (n < 0)
err_sys("str_echo: read error");
else
break;
}
}

//
// str_echo end
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// str_cli begin
//

void
str_cli(FILE *fp, int sockfd)
{
char	sendline[MAXLINE];
char	recvline[MAXLINE];

while (Fgets(sendline, MAXLINE, fp) != NULL) {
Writen(sockfd, sendline, strlen(sendline));

if (Readline(sockfd, recvline, MAXLINE) == 0)
err_quit("str_cli: server terminated prematurely");

Fputs(recvline, stdout);
}
}

//
// str_cli end
//////////////////////////////////////////////////////////////////////////

int
main(int argc, char **argv)
{
int					sockfd;
struct sockaddr_in	servaddr;

if (argc != 2)
err_quit("usage: tcpcli <IPaddress>");

// 申请一个套接字
sockfd = Socket(AF_INET, SOCK_STREAM, 0);

// 设置一个服务器套接字
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family	= AF_INET;
servaddr.sin_port	= htons(SERV_PORT);
inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

Connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));

str_cli(stdin, sockfd);

exit(0);
}


服务器端的代码:

/*************************************************************************
> File Name: tcpserv.c
> Author: mhsheng
> Mail:981065720@qq.com
> Created Time: Mon 14 Nov 2016 10:35:23 AM CST
************************************************************************/

// c standard head file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <signal.h>

// system i/o head file
#include <unistd.h>

// socket head file
#include <netinet/in.h>

#define MAXLINE 1024
#define LISTENQ 5
#define SERV_PORT 9066

void
err_quit(const char *str_err)
{
fprintf(stderr, "%s\n", str_err);
exit(-1);
}

void
err_sys(const char *str_err)
{
fprintf(stderr, "%s\n", str_err);
exit(-1);
}

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

return sockfd;
}

void
Connect(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)
{
if (connect(sockfd, myaddr, addrlen) < 0)
err_sys("connect error");
}

void
Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)
{
if (bind(sockfd, myaddr, addrlen) < 0)
err_sys("bind error");
}

void
Listen(int sockfd, int backlog)
{
if (listen(sockfd, backlog) < 0)
err_sys("listen error");
}

int
Accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)
{
int connfd;

for ( ; ; ) {
if ( (connfd = accept(sockfd, cliaddr, addrlen)) < 0) {
if (errno == EINTR) // 信号中断引起的错误
continue;
else
err_sys("accept error");
}
break;
}

return connfd;
}

void
Close(int sockfd)
{
if (close(sockfd) < 0)
err_sys("close error");
}

//////////////////////////////////////////////////////////////////////////
// Writen begin
//

ssize_t
writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;

ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
if (nwritten < 0 && errno == EINTR)
nwritten = 0; /* and call write() again */
else
return (-1);
}

nleft -= nwritten;
ptr += nwritten;
}

return (n);
}

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

//
// Writen end
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// Readline begin
//

static int read_cnt;
static char *read_ptr;
static char read_buf[MAXLINE];

static ssize_t
my_read(int fd, char *ptr)
{
if (read_cnt <= 0) {
for ( ; ; ) {
if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
if (errno == EINTR)
continue;
return -1;
} else if (read_cnt == 0)
return 0;

read_ptr = read_buf;
break;
}
}

read_cnt--;
*ptr = *read_ptr++;
return 1;
}

ssize_t
readline(int fd, void *vptr, size_t maxlen)
{
ssize_t n;
ssize_t rc;
char c;
char *ptr;

ptr = vptr;
for (n=1; n<maxlen; n++) {
if ( (rc = my_read(fd, &c)) == 1) {
*ptr++ = c;
if (c == '\n')
break;
} else if (rc == 0) {
*ptr = 0; /* EOF, n - 1 bytes were read */
return n-1;
} else {
return -1;
}
}

*ptr = 0;
return n;
}

ssize_t
Readline(int fd, void *ptr, size_t maxlen)
{
ssize_t n;

if ( (n = readline(fd, ptr, maxlen)) < 0)
err_sys("readline error");
return n;
}

//
// Readline end
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// wrapstdio begin
//

// Fgets begin
char *
Fgets(char *ptr, int n, FILE *stream)
{
char *rptr;

if ( (rptr = fgets(ptr, n, stream)) == NULL && ferror(stream))
err_sys("fgets error");

return rptr;
}
// Fgets end

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

//
// wrapstdio end
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// str_echo begin
//

void
str_echo(int sockfd)
{
char buf[MAXLINE];
ssize_t n;

for ( ; ; ) {
// 从套接字读取数据
while ( (n = read(sockfd, buf, MAXLINE)) > 0)
// 将读取的数据发送给客户端
Writen(sockfd, buf, n);

if (n < 0 && errno == EINTR)
continue;
else if (n < 0)
err_sys("str_echo: read error");
else
break;
}
}

//
// str_echo end
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// str_cli begin
//

void
str_cli(FILE *fp, int sockfd)
{
char sendline[MAXLINE];
char recvline[MAXLINE];

while (Fgets(sendline, MAXLINE, fp) != NULL) {
Writen(sockfd, sendline, strlen(sendline));

if (Readline(sockfd, recvline, MAXLINE) == 0)
err_quit("str_cli: server terminated prematurely");

Fputs(recvline, stdout);
}
}

//
// str_cli end
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// signal begin
//
typedef void Sigfunc(int);

Sigfunc *
signal(int signo, Sigfunc *func)
{
struct sigaction act;
struct sigaction oact;

act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;

if (signo == SIGALRM) {
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
} else {
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART;
#endif
}

if (sigaction(signo, &act, &oact) < 0)
return SIG_ERR;

return oact.sa_handler;
}

Sigfunc *
Signal(int signo, Sigfunc *func)
{
Sigfunc *sigfunc;

if ( (sigfunc = signal(signo, func)) == SIG_ERR)
err_sys("signal error");

return sigfunc;
}

//
// signal end
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// sig_chld begin
//

void
sig_chld(int signo)
{
pid_t pid;
int stat;

while ( (pid = waitpid(-1, &stat, WNOHANG)) < 0)
;

return ;
}

//
// sig_chld end
//////////////////////////////////////////////////////////////////////////

int
main(int argc, char **argv)
{
int listenfd;
int connfd;
pid_t pid;
struct sockaddr_in servaddr;

void sig_chld(int);

// 创建一个监听套接字描述符
listenfd = Socket(AF_INET, SOCK_STREAM, 0);

// 设置服务器的监听套接字
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

// 绑定套接字到套接字描述符
Bind(listenfd, (struct sockaddr *) & servaddr, sizeof(servaddr));

// 启动监听套接字
Listen(listenfd, LISTENQ);

// 处理子进程的信号 SIGCHLD
Signal(SIGCHLD, sig_chld);

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

if ( (pid = fork()) == 0) {
Close(listenfd);

str_echo(connfd);

exit(0);
}

Close(connfd);
}

exit(0);
}



Makefile文件:

PROGS	= tcpserv \
tcpcli

OBJS	= tcpserv.o \
tcpcli.o

All:	${PROGS}

tcpserv:	tcpserv.o
cc -o tcpserv tcpserv.o

tcpcli:		tcpcli.o
cc -o tcpcli tcpcli.o

clean:
rm $(PROGS) $(OBJS)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: