多进程多线程并发服务器&&本地通讯(TCP、UDP)

1.多进程并发服务器

#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <signal.h>
#include <wait.h>

#define IP "192.168.1.10"
#define PORT 8888

#define ERRMSG(msg) do\
{\
	fprintf(stderr, "__%d__", __LINE__);\
	exit(1);\
}while(0)

typedef void(*handerl_t)(int);

void handler(int sig)
{
	while(waitpid(-1, NULL,WNOHANG) > 0);
}
void massage(int newfd, struct sockaddr_in cin);

int main(int argc, const char *argv[])
{
	//回收僵尸进程
	handerl_t s = signal(17, handler);
	if(s == SIG_ERR)
	{
		ERRMSG("signal");
	}
	
	//创建字节流式套接字
	int sfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sfd < 0)
	{
		ERRMSG("socket");
	}

	//填充服务器自身地址族、IP和端口
	struct sockaddr_in sin, cin;//sin用于绑定自身地址信息,cin用于存储客户端地址信息
	sin.sin_family 		= AF_INET;
	sin.sin_port 		= htons(PORT);
	sin.sin_addr.s_addr = inet_addr(IP);
	socklen_t cinlen 	= sizeof(cin);
	
	//绑定到套接字上
	if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
	{
		ERRMSG("bind");
	}

	//设置被动监听状态
	if(listen(sfd, 10) < 0)
	{
		ERRMSG("listen");
	}

	int newfd = 0;
	pid_t pid = 0;;
	while(1)
	{
		//获取新的用于通讯的套接字文件描述符(父进程)
		newfd = accept(sfd, (struct sockaddr*)&cin, &cinlen);
		if(newfd < 0)
		{
			ERRMSG("accept");
		}
		printf("connect success\n");

		pid = fork();//创建子进程
		if(pid > 0)
		{
			close(newfd);//没有使用到
		
		}else if(pid == 0)
		{
			close(sfd);//没有使用到
			//接收或发送信息
			massage(newfd, cin);
			close(newfd);
			exit(0);//结束子进程
		}else
		{
			ERRMSG("fork");
		}
	}
	//关闭套接字
	
	return 0;
}
void massage(int newfd, struct sockaddr_in cin)
{
	while(1)
	{
		//接收信息(子进程)
		char buff[128]="";
		ssize_t res = 0;
		bzero(buff, sizeof(buff));

		res = recv(newfd, buff, sizeof(buff), 0);
		if(res < 0)
		{
			ERRMSG("recv");
		}
		if(res ==  0)
		{
			break;
		}
		printf("[%d]:%s\n", ntohs(cin.sin_port), buff);
		
		//发送信息(子进程)
		strcpy(buff, "receive completed");
		if(send(newfd, buff, sizeof(buff), 0) < 0)
		{
			ERRMSG("send");
		}
		
	}
}

测试结果 

 2.多线程并发服务器

#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>

#define IP "192.168.1.10"
#define PORT 8888

#define ERRMSG(msg) do\
{\
	fprintf(stderr, "__%d__", __LINE__);\
	exit(1);\
}while(0)

struct msg
{
	int newfd;
	struct sockaddr_in cin;
};

void* massage(void* arg);

int main(int argc, const char *argv[])
{
	//创建字节流式套接字
	int sfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sfd < 0)
	{
		ERRMSG("socket");
	}

	//填充服务器自身地址族、IP和端口
	struct sockaddr_in sin, cin;//sin用于绑定自身地址信息,cin用于存储客户端地址信息
	sin.sin_family 		= AF_INET;
	sin.sin_port 		= htons(PORT);
	sin.sin_addr.s_addr = inet_addr(IP);
	socklen_t cinlen 	= sizeof(cin);
	
	//绑定到套接字上
	if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
	{
		ERRMSG("bind");
	}

	//设置被动监听状态
	if(listen(sfd, 10) < 0)
	{
		ERRMSG("listen");
	}

	//主线程获取新的用于通讯的套接字文件描述符,子线程用于收发信息
	pthread_t tid;
	int newfd = 0;
	while(1)
	{
		newfd = accept(sfd, (struct sockaddr*)&cin, &cinlen);
		if(newfd < 0)
		{
			ERRMSG("accept");
		}
		printf("connect success\n");
		struct msg msg;
		msg.newfd = newfd;
		msg.cin   = cin;

		pthread_create(&tid, NULL, massage, (void*)&msg);//创建子线程
	}
	//关闭套接字
	close(sfd);
	close(newfd);
	return 0;
}

void* massage(void* arg)
{
	int newfd = (*(struct msg*)arg).newfd;
	struct sockaddr_in cin = (*(struct msg*)arg).cin;
	while(1)
	{
		//接收信息(子线程)
		char buff[128]="";
		ssize_t res = 0;
		bzero(buff, sizeof(buff));

		res = recv(newfd, buff, sizeof(buff), 0);
		if(res < 0)
		{
			ERRMSG("recv");
		}
		if(res ==  0)
		{
			break;
		}
		printf("newfd=%d  port=[%d]:%s\n", newfd, ntohs(cin.sin_port), buff);
		
		//发送信息(子线程)
		strcpy(buff, "receive completed");
		if(send(newfd, buff, sizeof(buff), 0) < 0)
		{
			ERRMSG("send");
		}
		
	}
}

 测试结果

 

3.tcp本地通讯

服务器代码:

#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/un.h>

#define ERRMSG(msg) do\
{\
	fprintf(stderr, "__%d__", __LINE__);\
	exit(1);\
}while(0)

void* massage(void* arg);

int main(int argc, const char *argv[])
{
	//创建字节流式套接字(本地通讯)
	int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
	if(sfd < 0)
	{
		ERRMSG("socket");
	}

	//要绑定的文件是否存在,存在则删除,需要的是由bind创建出来的文件
	if(access(argv[1], F_OK) == 0)
	{
		if(unlink(argv[1]) < 0)
		{
			ERRMSG("unlink");
		}
	}

	//填充服务器自身地址信息
	struct sockaddr_un sun, cun;//sun用于绑定自身地址信息,cun用于存储客户端地址信息
	sun.sun_family 		= AF_UNIX;
	strcpy(sun.sun_path, argv[1]);
	socklen_t cunlen 	= sizeof(cun);
	
	//绑定到套接字上
	if(bind(sfd, (struct sockaddr*)&sun, sizeof(sun)) < 0)
	{
		ERRMSG("bind");
	}

	//设置被动监听状态
	if(listen(sfd, 10) < 0)
	{
		ERRMSG("listen");
	}

	//主线程获取新的用于通讯的套接字文件描述符,子线程用于收发信息
	pthread_t tid;
	int newfd = 0;
	while(1)
	{
		newfd = accept(sfd, (struct sockaddr*)&cun, &cunlen);
		if(newfd < 0)
		{
			ERRMSG("accept");
		}
		printf("connect success\n");

		pthread_create(&tid, NULL, massage, (void*)&newfd);//创建子线程
	}
	//关闭套接字
	close(sfd);
	close(newfd);
	return 0;
}

void* massage(void* arg)
{
	int newfd = *(int*)arg;
	while(1)
	{
		//接收信息(子线程)
		char buff[128]="";
		ssize_t res = 0;
		bzero(buff, sizeof(buff));

		res = recv(newfd, buff, sizeof(buff), 0);
		if(res < 0)
		{
			ERRMSG("recv");
		}
		if(res ==  0)
		{
			break;
		}
		printf("newfd=%d %s\n", newfd, buff);
		
		//发送信息(子线程)
		strcpy(buff, "receive completed");
		if(send(newfd, buff, sizeof(buff), 0) < 0)
		{
			ERRMSG("send");
		}
		
	}
}

客户端代码

#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/un.h>

#define IP "192.168.1.10"
#define PORT 8888

#define ERRMSG(msg) do\
{\
	fprintf(stderr, "__%d__", __LINE__);\
	exit(1);\
}while(0)

int main(int argc, const char *argv[])
{
	//创建字节流式套接字(本地通讯)
	int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
	if(sfd < 0)
	{
		ERRMSG("socket");
	}

	//填充服务器地址信息
	struct sockaddr_un sun;
	sun.sun_family 		= AF_UNIX;
	strcpy(sun.sun_path, argv[1]);
	
	//连接服务器
	if(connect(sfd, (struct sockaddr*)&sun, sizeof(sun)) <0)
	{
		ERRMSG("connect");
	}

	char buff[128]="";
	ssize_t res = 0;
	while(1)
	{
		//发送信息
		bzero(buff, sizeof(buff));
		fgets(buff, sizeof(buff), stdin);
		buff[strlen(buff)-1] = '\0';
		if(send(sfd, buff, sizeof(buff), 0) < 0)
		{
			ERRMSG("send");
		}

		//接收信息
		bzero(buff, sizeof(buff));
		res = recv(sfd, buff, sizeof(buff), 0);
		if(res < 0)
		{
			ERRMSG("recv");
		}
		if(res ==  0)
		{
			break;
		}
		printf("%s\n", buff);
	}

	//关闭套接字
	close(sfd);
	return 0;
}

 测试结果

 4.udp本地通讯

服务器代码

#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/un.h>

#define ERRMSG(msg) do\
{\
	fprintf(stderr, "__%d__", __LINE__);\
	exit(1);\
}while(0)

int main(int argc, const char *argv[])
{
	//创建数据报式套接字(本地通讯)
	int sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
	if(sfd < 0)
	{
		ERRMSG("socket");
	}

	//要绑定的文件是否存在,存在则删除,需要的是由bind创建出来的文件
	if(access("./unix", F_OK) == 0)
	{
		if(unlink("./unix") < 0)
		{
			ERRMSG("unlink");
		}
	}

	//填充服务器自身地址信息
	struct sockaddr_un sun, cun;//sun用于绑定自身地址信息,cun用于存储客户端地址信息
	sun.sun_family 		= AF_UNIX;
	strcpy(sun.sun_path, "./unix");
	socklen_t cunlen 	= sizeof(cun);
	
	//绑定到套接字上
	if(bind(sfd, (struct sockaddr*)&sun, sizeof(sun)) < 0)
	{
		ERRMSG("bind");
	}

	char buff[128]="";
	ssize_t res = 0;
	//收发信息
	while(1)
	{
		//接收信息
		bzero(buff, sizeof(buff));
		res = recvfrom(sfd, buff, sizeof(buff), 0, (struct sockaddr*)&cun, &cunlen);
		if(res < 0)
		{
			ERRMSG("recv");
		}
		if(res ==  0)
		{
			break;
		}
		printf("%s\n", buff);

		//发送信息
		strcpy(buff, "receive completed");
		if(sendto(sfd, buff, sizeof(buff), 0, (struct sockaddr*)&cun, sizeof(cun)) < 0)
		{
			ERRMSG("send");
		}
	}

	//关闭套接字
	close(sfd);

	return 0;
}

客户端代码
 

#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/un.h>

#define ERRMSG(msg) do\
{\
	fprintf(stderr, "__%d__", __LINE__);\
	exit(1);\
}while(0)

int main(int argc, const char *argv[])
{
	//创建数据报式套接字(本地通讯)
	int sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
	if(sfd < 0)
	{
		ERRMSG("socket");
	}

	//要绑定的文件是否存在,存在则删除,需要的是由bind创建出来的文件
	if(access(argv[1], F_OK) == 0)
	{
		if(unlink(argv[1]) < 0)
		{
			ERRMSG("unlink");
		}
	}

	//填充客户端地址信息,不然服务器无法发送信息给客户端
	struct sockaddr_un cun;
	cun.sun_family 		= AF_UNIX;
	strcpy(cun.sun_path, argv[1]);

	//绑定到套接字上
	if(bind(sfd, (struct sockaddr*)&cun, sizeof(cun)) < 0)
	{
		ERRMSG("bind");
	}


	//填充服务器地址信息
	struct sockaddr_un sun;
	sun.sun_family 		= AF_UNIX;
	strcpy(sun.sun_path, "./unix");
	socklen_t sunlen 	= sizeof(sun);
	
	
	char buff[128]="";
	ssize_t res = 0;
	//收发信息
	while(1)
	{
		//发送信息
		bzero(buff, sizeof(buff));
		fgets(buff, sizeof(buff), stdin);
		buff[strlen(buff)-1] = '\0';
		if(sendto(sfd, buff, sizeof(buff), 0, (struct sockaddr*)&sun, sizeof(sun)) < 0)
		{
			ERRMSG("send");
		}

		//接收信息
		bzero(buff, sizeof(buff));
		res = recvfrom(sfd, buff, sizeof(buff), 0, NULL, NULL);
		if(res < 0)
		{
			ERRMSG("recv");
		}
		if(res ==  0)
		{
			break;
		}
		printf("%s\n", buff);
	}

	//关闭套接字
	close(sfd);

	return 0;
}

测试结果

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

傾语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值