第五章 TCP客户/服务器程序示例:
#include <sys/wait.h>
pid_t wait(int * statloc);
pid_t waitpid(pid_t pid, int * statloc, int options);
pid:
== -1, wait any child
> 0, wait child which child-gid == gid
== 0, wait any-child which child-group-id == parent-group-id
< -1, wait any-child which child-group-id == abs(pid)
options:
WCONTINUED, WNOHANG, WUNTRACED
macros of check statloc:
WIFEXITED(status) --> WEXITSTATUS(status)
WIFSIGNALED(status) --> WTERMSIG(status), WCOREDUMP(status)
WIFSTOPPED(status) --> WSTOPSIG(status)
WIFCONTINUED(status)
if statloc is NULL means we neednot child's exit-status
error return 0 or -1
示例:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "str_cli.h"
#define SERV_PORT 34567
int
main(int argc, char * argv[])
{
int sockfd;
struct sockaddr_in servaddr;
if (argc != 2) {
printf("usage: %s <IPaddress>\n", argv[0]);
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("socket error: %s\n", strerror(errno));
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
printf("inet_pton error: %s\n", strerror(errno));
exit(1);
}
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
printf("connect error: %s\n", strerror(errno));
exit(1);
}
str_cli(stdin, sockfd); /* do it all */
exit(0);
}
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "str_echo.h"
#define LISTENQ 5
#define SERV_PORT 34567
int
main(int argc, char * argv[])
{
int listenfd;
int connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in cliaddr;
struct sockaddr_in servaddr;
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("socket error: %s\n", strerror(errno));
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
printf("bind error: %s\n", strerror(errno));
exit(1);
}
if ((listen(listenfd, LISTENQ)) == -1) {
printf("listen error: %s\n", strerror(errno));
exit(1);
}
for ( ; ; ) {
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
if (connfd == -1) {
printf("accept error: %s\n", strerror(errno));
exit(1);
}
if ((childpid = fork()) < 0) {
printf("fork error: %s\n", strerror(errno));
exit(1);
}
else if (childpid == 0) {
if (close(listenfd) == -1) {
printf("close listenfd error: %s\n", strerror(errno));
exit(1);
}
str_echo(connfd); /* process the request */
exit(0);
}
else {
if (close(connfd) == -1) {
printf("close connfd error: %s\n", strerror(errno));
exit(1);
}
}
}
}
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "myio.h"
#define MAXLINE 1024
void
str_cli(FILE *fp, int sockfd)
{
int n;
char sendline[MAXLINE];
char recvline[MAXLINE];
while (fgets(sendline, MAXLINE, fp) != NULL) {
n = strlen(sendline);
if (writen(sockfd, sendline, n) != n) {
printf("writen error: %s\n", strerror(errno));
exit(1);
}
if ((n = readline(sockfd, recvline, MAXLINE)) < 0) {
printf("readline error: %s\n", strerror(errno));
exit(1);
}
else if (n == 0) {
printf("str_cli: server terminated prematurely\n");
exit(0);
}
if (fputs(recvline, stdout) == EOF) {
printf("fputs error: %s\n", strerror(errno));
exit(1);
}
}
if (ferror(fp)) {
printf("fget error: %s\n", strerror(errno));
exit(1);
}
}
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "myio.h"
#define MAXLINE 1024
void
str_echo(int sockfd)
{
ssize_t n;
char buf[MAXLINE];
again:
while ((n = read(sockfd, buf, MAXLINE)) > 0) {
if (writen(sockfd, buf, n) != n) {
printf("writen error: %s\n", strerror(errno));
exit(1);
}
}
if (n < 0) {
if (errno == EINTR) {
goto again;
}
else {
printf("str_echo: read error: %s\n", strerror(errno));
exit(0);
}
}
}
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "str_cli.h"
#define SERV_PORT 34567
int
main(int argc, char * argv[])
{
int i;
int sockfd[5];
struct sockaddr_in servaddr;
if (argc != 2) {
printf("usage: %s <IPaddress>\n", argv[0]);
exit(1);
}
for (i = 0; i < 5; ++i) {
if ((sockfd[i] = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("socket error: %s\n", strerror(errno));
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
printf("inet_pton error: %s\n", strerror(errno));
exit(1);
}
if (connect(sockfd[i], (struct sockaddr *)&servaddr,
sizeof(servaddr)) == -1) {
printf("connect error: %s\n", strerror(errno));
exit(1);
}
}
str_cli(stdin, sockfd[0]); /* do it all */
exit(0);
}
#include <stdio.h>
#include <errno.h>
#include <signal.h>
typedef void Sigfunc(int);
Sigfunc *
my_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;
}
else {
return oact.sa_handler;
}
}
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "str_echo.h"
#include "my_signal.h"
#define LISTENQ 5
#define SERV_PORT 34567
void
sig_chld(int signo)
{
pid_t pid;
int stat;
while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) { /* waitpid + WNOHANG */
printf("child %d terminated\n", pid);
}
return;
}
int
main(int argc, char * argv[])
{
int listenfd;
int connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in cliaddr;
struct sockaddr_in servaddr;
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("socket error: %s\n", strerror(errno));
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
printf("bind error: %s\n", strerror(errno));
exit(1);
}
if ((listen(listenfd, LISTENQ)) == -1) {
printf("listen error: %s\n", strerror(errno));
exit(1);
}
if (my_signal(SIGCHLD, sig_chld) == SIG_ERR) { /* must call waitpid() */
printf("my_signal error: %s\n", strerror(errno));
exit(1);
}
for ( ; ; ) {
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
if (connfd < 0) {
if (errno == EINTR) {
continue; /* back to for */
}
else {
printf("accept error: %s\n", strerror(errno));
exit(1);
}
}
if ((childpid = fork()) < 0) {
printf("fork error: %s\n", strerror(errno));
exit(1);
}
else if (childpid == 0) {
if (close(listenfd) == -1) {
printf("close listenfd error: %s\n", strerror(errno));
exit(1);
}
str_echo(connfd); /* process the request */
exit(0);
}
else {
if (close(connfd) == -1) {
printf("close connfd error: %s\n", strerror(errno));
exit(1);
}
}
}
}
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "myio.h"
void
str_echo(int sockfd)
{
long arg1;
long arg2;
ssize_t n;
char line[MAXLINE];
for ( ; ; ) {
if ((n = readline(sockfd, line, MAXLINE)) < 0) {
printf("readline error: %s\n", strerror(errno));
exit(1);
}
else if (n == 0) {
return; /* connection closed by other end */
}
if (sscanf(line, "%ld%ld", &arg1, &arg2) == 2) {
snprintf(line, sizeof(line), "%ld\n", arg1 + arg2);
}
else {
snprintf(line, sizeof(line), "input error\n");
}
n = strlen(line);
if (writen(sockfd, line, n) != n) {
printf("writen error: %s\n", strerror(errno));
exit(1);
}
}
}
struct args {
long arg1;
long arg2;
};
struct result {
long sum;
};
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "sum.h"
#include "myio.h"
#define MAXLINE 1024
void
str_cli(FILE * fp, int sockfd)
{
int n;
char sendline[MAXLINE];
struct args arg;
struct result ret;
while (fgets(sendline, MAXLINE, fp) != NULL) {
if (sscanf(sendline, "%ld%ld", &arg.arg1, &arg.arg2) != 2) {
printf("invalid input: %s", sendline);
continue;
}
if (writen(sockfd, &arg, sizeof(arg)) != sizeof(arg)) {
printf("writen error: %s\n", strerror(errno));
exit(1);
}
if ((n = readn(sockfd, &ret, sizeof(ret))) == 0) {
printf("str_cli: server terminated prematurely");
exit(0);
}
else if (n != sizeof(ret)) {
printf("cli %d/%d readn error: %s\n", n, sizeof(ret), strerror(errno));
exit(1);
}
else {
printf("%ld\n", ret.sum);
}
}
}
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "sum.h"
#include "myio.h"
void
str_echo(int sockfd)
{
ssize_t n;
struct args arg;
struct result ret;
for ( ; ; ) {
if ((n = readn(sockfd, &arg, sizeof(arg))) == 0) {
return; /* connection closed by other end */
}
else if (n != sizeof(arg)) {
printf("readn error: %s\n", strerror(errno));
exit(1);
}
ret.sum = arg.arg1 + arg.arg2;
if (writen(sockfd, &ret, sizeof(ret)) != sizeof(ret)) {
printf("writen error: %s\n", strerror(errno));
exit(1);
}
}
}
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "my_signal.h"
#define SERV_PORT 34567
void
sig_pipe(int signo)
{
printf("SIGPIPE received\n");
return;
}
int
main(int argc, char * argv[])
{
int sockfd;
struct sockaddr_in servaddr;
if (argc != 2) {
printf("usage: %s <IPaddress>\n", argv[0]);
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("socket error: %s\n", strerror(errno));
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
printf("inet_pton error: %s\n", strerror(errno));
exit(1);
}
if (my_signal(SIGPIPE, sig_pipe) == SIG_ERR) { /* must call waitpid() */
printf("my_signal error: %s\n", strerror(errno));
exit(1);
}
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
printf("connect error: %s\n", strerror(errno));
exit(1);
}
sleep(2);
if (write(sockfd, "hello", 5) != 5) {
printf("write 1 error: %s\n", strerror(errno));
exit(1);
}
sleep(2);
if (write(sockfd, "world", 5) != 5) {
printf("write 2 error: %s\n", strerror(errno));
exit(1);
}
exit(0);
}