一.进程实现TCP并发服务器
#include <func.h>
#define PORT 6666
#define IP "192.168.124.42"
void handler(int arm)
{
while(waitpid(-1,NULL,WNOHANG) > 0);
}
int main(int argc, const char *argv[])
{
//接受17号信号
signal(17, handler);
int sfd = socket(AF_INET,SOCK_STREAM,0); //创建流式套接字
printf("sfd create success\n");
//绑定 ip 和端口
//填充结构体信息
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
bind(sfd, (struct sockaddr*)&sin, sizeof(sin));
//设置为监听模式
listen(sfd,128);
//接受客户端信息结构体
struct sockaddr_in cin;
socklen_t len = sizeof(cin);
while(1)
{
//创建新的套接字
//父进程进行接受信息
int newfd = accept(sfd, (struct sockaddr*)&cin, &len);
printf("newfd= %d 客户端连接成功 __%d__\n", newfd, __LINE__);
int cpid = fork(); //创建父子进程
if(0 == cpid ) //子进程进行信息传递
{
close(sfd);
char arr[128] = "";
int a = 0;
while(1)
{
//收
bzero(arr, sizeof(arr));
a = recv(newfd, arr, sizeof(arr), 0);
if(a < 0)
{
ERR_MSG("recv");
return -1;
}
if(a == 0)
{
printf("newfd= %d 客户端退出\n", newfd);
}
printf("接受成功 客户端信息arr= %s\n", arr);
//发
strcpy(arr, "~_~");
send(newfd, arr,sizeof(arr),0);
printf("%s 发送成功\n", arr);
}
exit(0);
}
}
close(sfd);
return 0;
}
现象
二、线程
#include <func.h>
#include <pthread.h>
#define PORT 6666
#define IP "192.168.124.42"
struct demo
{
int newfd;
struct sockaddr_in cin; //接收客户端的地址信息
};
int chlid(int newfd,struct sockaddr_in cin);
void* callbake(void * arg)
{
int newfd = ((struct demo*)arg)->newfd; //传参数
struct sockaddr_in cin = ((struct demo*)arg)->cin;
chlid(newfd,cin);//传到函数内部相当另存一个 newfd
close(newfd);
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
//创建流式套接
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd < 0)
{
ERR_MSG("sfd");
return -1;
}
printf("socket create succes sfd=%d __%d__\n", sfd, __LINE__);
//定义并填充地址信息结构体,给服务器绑定
//真实的地址信息结构体根据地址族指定 AF_INET :man ip(7)
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT); //端口号的网络字节序 : 1024-49151
sin.sin_addr.s_addr = inet_addr(IP); //本机号的网络字节序列
//绑定服务器自身的地址信息----必须绑定
if(bind(sfd,(struct sockaddr*) &sin, sizeof(sin)) <0)
{
ERR_MSG("bind");
return -1;
}
//将套接字设置为被动监听状态
if(listen(sfd, 128) <0)
{
ERR_MSG("listen");
return -1;
}
printf("listen succress __%d__\n", __LINE__);
struct demo info; //定义结构体
socklen_t addrlen = sizeof(info.cin);
//获取连接成功的客户端信息,生成一个新的套接字
while(1)
{
info.newfd = accept(sfd,(struct sockaddr *)&info.cin, &addrlen);
if(info.newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("newfd= %d 客户端连接成功 __%d__\n",info.newfd,__LINE__);
pthread_t tid;
pthread_create(&tid, NULL,callbake,(void*)&infoi); // 创建一个线程
pthread_detach(tid);
}
//关闭文件描述符
if(close(sfd) < 0)
{
ERR_MSG("close");
return -1;
}
return 0;
}
int chlid(int newfd,struct sockaddr_in cin)
{
ssize_t a = 0;
ssize_t b = 0;
char arr[128] = "";
char crr[128] = "";
while(1)
{
//接收客户端数据
bzero(arr, sizeof(arr));
a = recv(newfd, arr, sizeof(arr), 0);
if(a < 0 )
{
ERR_MSG("recv");
return -1;
}
if(a == 0)
{
printf("对端关闭发送结束\n");
printf("[%s:%d]\n",inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));//客户端的端口 ip
break;
}
printf("[%s:%d]\n",inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));//客户端的端口 ip
printf("对端成功接收\n");
printf("客户端信息:%s\n", arr);
//向客户端发送数据
printf("请输入需要发送的数据-->");
fgets(crr,sizeof(crr), stdin);
b = send(newfd, crr, sizeof(crr), 0);
printf("发送成功");
}
}
现象