代码是从别的地方抄来的,如有错漏请多多包涵
client.c
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <time.h>
#include <poll.h>
#include <sys/epoll.h>
#include "common.h"
//#include <netdb.h>
//#include <netinet/in.h>
//#include <sys/uio.h>
//#include <sys/wait.h>
//#include <sys/un.h>
void str_cli(FILE *fp, int sockfd)
{
char sendline[MAXLINE], recvline[MAXLINE];
int len;
//从终端获取一行字符串,将其写入套接字
//然后从套接字一行字符串,将其写入终端
while (fgets_s(sendline, MAXLINE, fp) != NULL)
{
write_s(sockfd, sendline, strlen(sendline));
len = read_s(sockfd, recvline, MAXLINE);
if (len == 0)
err_quit("str_cli: server terminated prematurely");
recvline[len] = 0;
fputs(recvline, stdout);
}
}
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
if (argc != 2)
err_quit("ustruct sockaddrge: client <IPAddress>");
//创建用于TCP协议的套接字
sockfd = socket_s(AF_INET, SOCK_STREAM, 0);
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
//将程序的参数1(argv[1])转换成套接字地址结构
inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
向服务器发起连接,连接成功后client_socket代表了客户机和服务器的一个socket连接
connect_s(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
str_cli(stdin, sockfd);
return 0;
}
server.c
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <time.h>
#include <sys/wait.h>
#include <poll.h>
#include <sys/epoll.h>
#include "common.h"
int main(int argc, char **argv)
{
int listenfd, connfd, sockfd, epfd;
int i, maxi, nfds;
ssize_t n;
char buf[MAXLINE];
socklen_t clilen;
struct sockaddr_in cliaddr;
struct sockaddr_in servaddr;
//声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
struct epoll_event ev, events[256];
//创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大
epfd = epoll_create(256);
//创建用于TCP协议的套接字
listenfd = socket_s(AF_INET, SOCK_STREAM, 0);
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
//把socket和socket地址结构联系起来
bind_s(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
//开始监听LISTENQ端口
listen_s(listenfd, LISTENQ);
//设置与要处理的事件相关的文件描述符和事件
ev.data.fd = listenfd;
ev.events = EPOLLIN | EPOLLET;
//注册epoll事件
epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);
maxi = 0;
while (1)
{
//等待epoll事件的发生
//返回需要处理的事件数目nfds,如返回0表示已超时。
nfds = epoll_wait(epfd, events, 20, 500);
//处理所发生的所有事件
for (i = 0; i < nfds; ++i)
{
//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。
if (events[i].data.fd == listenfd)
{
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
printf("connection from %s, port %d.\n", inet_ntop(AF_INET, (void *)&cliaddr.sin_addr, buf, sizeof(buf)), ntohs(cliaddr.sin_port));
//设置用于读操作的文件描述符和事件
ev.data.fd = connfd;
ev.events = EPOLLIN | EPOLLET;
//注册事件
epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev);
}
//如果是已经连接的用户,并且收到数据,那么进行读入。
else if (events[i].events & EPOLLIN)
{
sockfd = events[i].data.fd;
if (sockfd < 0)
continue;
n = read(sockfd, buf, MAXLINE);
if (n < 0)
{
// Connection Reset:你连接的那一端已经断开了,
//而你却还试着在对方已断开的socketfd上读写数据!
if (errno == ECONNRESET)
{
close_s(sockfd);
events[i].data.fd = -1;
}
else
err_quit("read error");
}
//如果读入的数据为空
else if (n == 0)
{
close_s(sockfd);
events[i].data.fd = -1;
}
else
{
//设置用于写操作的文件描述符和事件
ev.data.fd = sockfd;
ev.events = EPOLLOUT | EPOLLET;
//注册事件
epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
}
}
//如果有数据发送
else if (events[i].events & EPOLLOUT)
{
sockfd = events[i].data.fd;
write_s(sockfd, buf, n);
//设置用于读操作的文件描述符和事件
ev.data.fd = sockfd;
ev.events = EPOLLIN | EPOLLET;
//注册事件
epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
}
}
}
return 0;
}
common.c
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <time.h>
#include <sys/wait.h>
#include "common.h"
sig_t signal_s(int __sig, sig_t __handler)
{
sig_t ret = signal(__sig, __handler);
if (ret == SIG_ERR)
err_quit("signal error");
return ret;
}
int select_s(int __nfds, fd_set *__restrict__ __readfds, fd_set *__restrict__ __writefds,
fd_set *__restrict__ __exceptfds, struct timeval *__restrict__ __timeout)
{
int ret = select(__nfds, __readfds, __writefds, __exceptfds, __timeout);
if (ret < 0)
err_quit("select error");
return ret;
}
ssize_t read_s(int __fd, void *__buf, size_t __nbytes)
{
int ret = read(__fd, __buf, __nbytes);
if (ret < 0)
err_quit("read error");
return ret;
}
int shutdown_s(int __fd, int __how)
{
int ret = shutdown(__fd, __how);
if (ret < 0)
err_quit("shutdown error");
return ret;
}
int socket_s(int socket_family, int socket_type, int protocol)
{
int sockfd = socket(socket_family, socket_type, protocol);
if (sockfd < 0)
{
perror("create socket error");
exit(EXIT_FAILURE);
}
return sockfd;
}
int bind_s(int __fd, const struct sockaddr *__addr, socklen_t __len)
{
int ret = bind(__fd, __addr, __len);
if (ret < 0)
{
perror("bind socket fail");
exit(EXIT_FAILURE);
}
return ret;
}
int listen_s(int __fd, int __n)
{
int ret = listen(__fd, __n);
if (ret < 0)
{
perror("listen error");
exit(EXIT_FAILURE);
}
return ret;
}
int connect_s(int __fd, const struct sockaddr *__addr, socklen_t __len)
{
int ret = connect(__fd, __addr, __len);
if (ret < 0)
{
perror("connect eror");
exit(EXIT_FAILURE);
}
return ret;
}
ssize_t write_s(int __fd, const void *__buf, size_t __n)
{
int ret = write(__fd, __buf, __n);
if (ret < 0)
err_quit("write error");
return ret;
}
void err_quit(char *message)
{
printf("%s\n", message);
exit(EXIT_FAILURE);
}
in_addr_t inet_addr_s(const char *__cp)
{
in_addr_t ret = inet_addr(__cp);
if (ret < 0)
perror("inet_addr error");
return ret;
}
int fork_s(void)
{
int ret;
ret = fork();
if (ret < 0)
err_quit("fork error");
return ret;
}
char *fgets_s(char *__restrict__ __s, int __n, FILE *__restrict__ __stream)
{
char *rptr;
if ((rptr = fgets(__s, __n, __stream)) == NULL && ferror(__stream))
err_quit("fgets error");
return rptr;
}
int close_s(int fd)
{
int ret = close(fd);
if (ret < 0)
err_quit("close error");
return ret;
}
static int read_cnt;
static int *read_ptr;
static int read_buf[MAXLINE];
/* 一直读,知道读取到了东西为止, 放在read_buf里面, 然后还获取了最后一个字节 */
static int my_read(int fd, char *ptr)
{
if (read_cnt <= 0)
{
again:
if ((read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0)
{
if (errno == EINTR)
goto again;
return (-1);
}
else if (read_cnt = 0)
return 0;
read_ptr = read_buf;
}
read_cnt--;
*ptr = *read_ptr++;
return (-1);
}
ssize_t readline(int fd, void *vptr, size_t maxlen)
{
ssize_t n, rc;
char c, *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;
return (n - 1);
}
else
return (-1);
}
*ptr = 0;
if (n < 0)
err_quit("readline error");
return n;
}
void fputs_s(const char *__restrict__ __s, FILE *__restrict__ __stream)
{
if (fputs(__s, __stream) == EOF)
err_quit("fputs erro");
}
common.h
#ifndef _COMMON_H_
#define _COMMON_H_
#define SERV_PORT 1043
#define MAXLINE 4096
#define LISTENQ 1024
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) < (b) ? (b) : (a))
int socket_s(int socket_family, int socket_type, int protocol);
int bind_s(int __fd, const struct sockaddr *__addr, socklen_t __len);
int listen_s(int __fd, int __n);
int connect_s(int __fd, const struct sockaddr *__addr, socklen_t __len);
in_addr_t inet_addr_s(const char *__cp);
int fork_s(void);
int close_s(int fd);
void err_quit(char *message);
ssize_t write_s(int __fd, const void *__buf, size_t __n);
char *fgets_s(char *__restrict__ __s, int __n, FILE *__restrict__ __stream);
ssize_t readline(int fd, void *vptr, size_t maxlen);
void fputs_s(const char *__restrict__ __s, FILE *__restrict__ __stream);
int select_s(int __nfds, fd_set *__restrict__ __readfds, fd_set *__restrict__ __writefds,
fd_set *__restrict__ __exceptfds, struct timeval *__restrict__ __timeout);
ssize_t read_s(int __fd, void *__buf, size_t __nbytes);
int shutdown_s(int __fd, int __how);
#endif
运行:
root@orangepizero2:~/test# ./server.rap
connection from 0.0.0.0, port 0.
^C
root@orangepizero2:~/test#
root@orangepizero2:~/test# ./client.rap 192.168.3.95
ce shui hui she xin xi
ce shui hui she xin xi