多进程
还是以大小写转换为例子
cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "wrap.h"
#include <ctype.h>
#include <signal.h>
#include <sys/wait.h>
#define SERV_PORT 9527
void catch_child(int signum)//信号,用来回收子进程
{
while((waitpid(0,NULL,WNOHANG)) > 0);
return;
}
int main(int argc,char* argv[])
{
int lfd,cfd;
int ret,i;
char buf[BUFSIZ],client_IP[1024];
pid_t pid;
struct sockaddr_in serv_addr,clit_addr;
socklen_t clit_addr_len;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
serv_addr.sin_addr.s_addr = htonl (INADDR_ANY);
lfd = Socket(AF_INET,SOCK_STREAM,0);
Bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
Listen(lfd,128);
clit_addr_len = sizeof(clit_addr);
while(1)
{
cfd = Accept(lfd,(struct sockaddr*)&clit_addr,&clit_addr_len);
pid = fork();//创建子进程
if(pid < 0)
{
perr_exit("fork error");
}
else if(pid == 0)
{
printf("client ip:%s port%d\n",
inet_ntop(AF_INET, &clit_addr.sin_addr.s_addr, client_IP, sizeof(client_IP)),
ntohs(clit_addr.sin_port));//打印客户端网络信息
close(lfd);
break;
}
else
{
//父进程调用信号回收子进程
struct sigaction act;
act.sa_handler = catch_child;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
ret = sigaction(SIGCHLD,&act,NULL);
if(ret != 0)
{
perr_exit("signal error");
}
close(cfd);
continue;
}
}
if(pid == 0)//大小写转换
{
for(;;)
{
ret = read(cfd,buf,sizeof(buf));
if(ret == 0)
{
close(cfd);
exit(1);
}
for(i = 0;i < ret;i++)
{
buf[i] = toupper(buf[i]);
}
write(cfd,buf,ret);
write(STDOUT_FILENO,buf,ret);
}
}
return 0;
}
多线程
cpp
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include "wrap.h"
#define MAXLINE 8192
#define SERV_PORT 8000
struct s_info { //定义一个结构体, 将地址结构跟cfd捆绑
struct sockaddr_in cliaddr;
int connfd;
};
void *do_work(void *arg)
{
int n,i;
struct s_info *ts = (struct s_info*)arg;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN]; //#define INET_ADDRSTRLEN 16 可用"[+d"查看
while (1) {
n = Read(ts->connfd, buf, MAXLINE); //读客户端
if (n == 0) {
printf("the client %d closed...\n", ts->connfd);
break; //跳出循环,关闭cfd
}
printf("received from %s at PORT %d\n",
inet_ntop(AF_INET, &(*ts).cliaddr.sin_addr, str, sizeof(str)),
ntohs((*ts).cliaddr.sin_port)); //打印客户端信息(IP/PORT)
for (i = 0; i < n; i++)
buf[i] = toupper(buf[i]); //小写-->大写
Write(STDOUT_FILENO, buf, n); //写出至屏幕
Write(ts->connfd, buf, n); //回写给客户端
}
Close(ts->connfd);
return (void *)0;
}
int main(void)
{
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddr_len;
int listenfd, connfd;
pthread_t tid;
struct s_info ts[256]; //创建结构体数组.
int i = 0;
listenfd = Socket(AF_INET, SOCK_STREAM, 0); //创建一个socket, 得到lfd
bzero(&servaddr, sizeof(servaddr)); //地址结构清零
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //指定本地任意IP
servaddr.sin_port = htons(SERV_PORT); //指定端口号
Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); //绑定
Listen(listenfd, 128); //设置同一时刻链接服务器上限数
printf("Accepting client connect ...\n");
while (1) {
cliaddr_len = sizeof(cliaddr);
connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); //阻塞监听客户端链接请求
ts[i].cliaddr = cliaddr;
ts[i].connfd = connfd;
pthread_create(&tid, NULL, do_work, (void*)&ts[i]);
pthread_detach(tid); //子线程分离,防止僵线程产生.
i++;
}
return 0;
}