多进程并发模板
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <ctype.h>
#include "wrap.h"
#define MAX_LINE 80
#define SERV_PORT 8000
void do_sig_child(int num) //通过子进程结束时发送给父进程信号回收子进程
{
while (waitpid(0, 0, 0) > 0)//阻塞回收
;
}
int main(void)
{
int servfd, clifd;
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddrlen;
int i, len;
pid_t pid;
char buf[MAX_LINE];
char str[MAX_LINE];
struct sigaction act;
act.sa_handler = do_sig_child;//设置信号捕捉函数
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGCHLD, &act, NULL);
servfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));//初始化服务器地址信息
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
Bind(servfd, (struct sockaddr *)&servaddr, sizeof(servaddr));//绑定
Listen(servfd, 20);
printf("Accepting ...\n");
while (1) {
cliaddrlen = sizeof(cliaddr);
clifd = Accept(servfd, (struct sockaddr *)&cliaddr, &cliaddrlen);
pid = fork();
if (pid == 0) { //子进程
Close(servfd);
printf("Receving : %s, PORT: %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));
while (1) {
len = Read(clifd, buf, sizeof(buf));
if (len == 0) { //为0时说明客户端关闭连接,跳出循环
printf("one client exit\n");
break;
}
for (i = 0; i < len; i++)
buf[i] = toupper(buf[i]);
Write(clifd, buf, len);
}
Close(clifd);
return 0;//结束子进程
} else if (pid > 0) {
Close(clifd);
} else {
perr_exit("fock error");
}
}
Close(servfd);
return 0;
}
多线程并发模板
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "wrap.h"
#include <strings.h>
#include <pthread.h>
#include <string.h>
#include <ctype.h>
#define SERV_PORT 8000
#define MAX_LINE 80
int clifd; //设置全局变量,一遍让线程可以访问
void *th_fun(void *arg)
{
int clientfd = clifd;
int i, len;
char buf[MAX_LINE];
while (1) {
len = Read(clientfd, buf, sizeof(buf));
if (len == 0) {
printf("one client exit\n");
break;
}
for (i = 0; i < len; i++)
buf[i] = toupper(buf[i]);
Write(clientfd, buf, len);
}
Close(clientfd);
return NULL;
}
int main(void)
{
int servfd;
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddrlen;
char str[MAX_LINE];
pthread_t tid;
pthread_attr_t attr;
int n;
pthread_attr_init(&attr);//设置线程分离属性
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
servfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));//初始化地址信息
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
Bind(servfd, (struct sockaddr *)&servaddr, sizeof(servaddr));//绑定
Listen(servfd, 20);
printf("Accepting ...\n");
while (1) {
cliaddrlen = sizeof(cliaddr);
clifd = Accept(servfd, (struct sockaddr *)&cliaddr, &cliaddrlen);
printf("Rece: %s, PORT: %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));
n = pthread_create(&tid, &attr, th_fun, NULL);//创建线程
if (n != 0)//出错处理
fprintf(stderr, "pthread_create:%s\n", strerror(n));
}
Close(servfd);
return 0;
}
wrap函数出错处理
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
void perr_exit(const char *str)
{
perror(str);
exit(1);
}
int Socket(int family, int type, int protocol)
{
int n;
if ((n = socket(family, type, protocol)) < 0)
perr_exit("socket error");
return n;
}
void Bind(int sockfd, const struct sockaddr *sa, socklen_t salen)
{
if (bind(sockfd, sa, salen) < 0)
perr_exit("bind error");
}
void Listen(int sockfd, int backlog)
{
if (listen(sockfd, backlog) < 0)
perr_exit("listen error");
}
int Accept(int sockfd, struct sockaddr *sa, socklen_t *salenptr)
{
int n;
while ((n = accept(sockfd, sa, salenptr)) < 0) {
if ((errno == ECONNABORTED) || (errno == EINTR))//如果是被信号打断的,重新读取
;
else
perr_exit("accept error");
}
return n;
}
int Read(int fd, void *ptr, int nbytes)
{
int n;
while ((n = read(fd, ptr, nbytes)) == -1) {
if (errno == EINTR)//如果是被信号打断的,重新读取
;
else
return -1;
}
return n;
}
int Write(int fd, const void *ptr, int nbytes)
{
int n;
while ((n = write(fd, ptr, nbytes)) == -1) {
if (errno == EINTR)//如果是被信号打断的,重新写
;
else
return -1;
}
return n;
}
void Close(int fd)
{
if (close(fd) == -1)
perr_exit("close error");
}
wrap.h
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#ifndef __WRAP_H_
#define __WRAP_H_
void perr_exit(const char *str);
int Accept(int sockfd, struct sockaddr *sa, socklen_t *salenptr);
int Socket(int family, int type, int protocol);
void Bind(int sockfd, const struct sockaddr *sa, socklen_t salen);
void Listen(int sockfd, int backlog);
int Read(int fd, void *ptr, int nbytes);
int Write(int fd, const void *ptr, int nbytes);
void Close(int fd);
#endif
客户端
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <strings.h>
#include "wrap.h"
#define SERV_PORT 8000
#define SERV_IP "192.168.188.133"
#define MAX_LINE 80
int main(void)
{
int servfd;
struct sockaddr_in servaddr;
int len;
char buf[MAX_LINE];
// while (1) {
servfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, SERV_IP, &servaddr.sin_addr);
connect(servfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
while (1) {
len = Read(STDIN_FILENO, buf, sizeof(buf));
Write(servfd, buf, len);
// Write(servfd, "hello", 5);
len = Read(servfd, buf, sizeof(buf));
Write(STDOUT_FILENO, buf, len);
}
return 0;
}