server.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <strings.h>
#include <sys/wait.h>
#include "wrap.h"
#define SERV_PORT 8888
void wait_child(int signo)
{
while (waitpid(0, NULL, WNOHANG) > 0)
{
;
}
}
int main()
{
int i;
int n;
int cfd;
int opt = 1;
int listenfd;
pid_t pid;
char buf[BUFSIZ];
char clie_IP[BUFSIZ];
socklen_t clie_addr_len;
struct sockaddr_in serv_addr, clie_addr;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
Bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
Listen(listenfd, 128);
while (1)
{
clie_addr_len = sizeof(clie_addr);
cfd = Accept(listenfd, (struct sockaddr *)&clie_addr, &clie_addr_len);
pid = fork();
if (0 == pid)
{
Close(listenfd);
while (1)
{
n = Read(cfd, buf, sizeof(buf));
if (0 == n)
{
break;
}
printf("Client IP: %s, Port: %d\n",
inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, clie_IP, sizeof(clie_IP)),
ntohs(clie_addr.sin_port));
for (i = 0; i < n; ++i)
{
buf[i] = toupper(buf[i]);
}
Write(cfd, buf, n);
}
Close(cfd);
return 0;
}
else if (pid > 0)
{
Close(cfd);
signal(SIGCHLD, wait_child);
}
else
{
perr_exit("fork");
}
}
return 0;
}
wrap.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
void perr_exit(const char *str)
{
perror(str);
exit(-1);
}
int Socket(int family, int type, int protocol)
{
int n;
n = socket(family, type, protocol);
if (n < 0)
{
perr_exit("socket error");
}
return n;
}
int Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{
int n;
n = bind(fd, sa, salen);
if (n < 0)
{
perr_exit("bing error");
}
return n;
}
int Listen(int fd, int backlog)
{
int n;
n = listen(fd, backlog);
if (n < 0)
{
perr_exit("listen error");
}
return n;
}
int Connect(int fd, const struct sockaddr *sa, socklen_t salen)
{
int n;
n = connect(fd, sa, salen);
if (n < 0)
{
perr_exit("connect error");
}
return n;
}
int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
{
int n;
again:
n = accept(fd, sa, salenptr);
if (n < 0)
{
if (errno == ECONNABORTED || errno == EINTR)
{
goto again;
}
else
{
perr_exit("accept error");
}
}
}
ssize_t Read(int fd, void *ptr, size_t nbytes)
{
ssize_t n;
again:
n = read(fd, ptr, nbytes);
if (-1 == n)
{
if (EINTR == errno)
{
goto again;
}
else
{
return -1;
}
}
return n;
}
ssize_t Write(int fd, const void *ptr, size_t nbytes)
{
ssize_t n;
again:
n = write(fd, ptr, nbytes);
if (-1 == n)
{
if (EINTR == errno)
{
goto again;
}
else
{
return -1;
}
}
return n;
}
int Close(int fd)
{
int n;
n = close(fd);
if (-1 == n)
{
perr_exit("close error");
}
return n;
}