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)
{
//如果>0,继续回收子进程
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]; //用来存放客户端IP
socklen_t clie_addr_len;
struct sockaddr_in serv_addr, clie_addr;
//参数1: AF_INET ->ipv4 AF_INET6 ->ipv6
//参数2:SOCK_STREAM -> TCP SOCK_DGRAM -> UDP
//参数3:传0 表示使用默认协议。
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); //网络地址为INADDR_ANY,这个宏表示本地的任意IP地址
Bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); //由于历史原因,需强制转换为 struct sockaddr * 类型
Listen(listenfd, 128); //允许同时监听的客户端请求, 最大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;
}
server.c
#include <stdio.h>
#include <unistd.h>
#