Socket编程(C语言实现)—— 为什么流式传输类似于管道?不区分边界?

1、管道实现:

(1)代码实现:[root@localhost pipe]# cat pipe.c 

#include 
#include 

int main(void)
{
	int i =  0;
	int aiPipe[2] = {0};
	pid_t stPid = {0};
	char acSendBuf[2] = {0};
	char acRecvBuf[4] = {0};

	if(0 != pipe(aiPipe))
	{
		printf("创建管道失败!\n");
		return 0;
	}

	stPid = fork();
	if(0 == stPid)
	{
		sleep(2);
		printf("\n接收的长度是%d\n",read(aiPipe[0], acRecvBuf, sizeof(acRecvBuf)));
		for(i = 0; i < sizeof(acRecvBuf); i++)
		{
			printf("acRecvBuf[%d]:%d\n", i, acRecvBuf[i]);
		}
	}
	else
	{
		for(i = 0; i < 2; i++)
		{
			acSendBuf[0] = i + 1;
			acSendBuf[1] = i + 1;

			printf("发送长度是%d\n", write(aiPipe[1], acSendBuf, sizeof(acSendBuf)));
		}
	}

	return 0;
}

(2)编译执行:[root@localhost pipe]# make pipe

(3)结果显示:

[root@localhost pipe]# ./pipe
发送长度是2
发送长度是2
[root@localhost pipe]# 
接收的长度是4
acRecvBuf[0]:1
acRecvBuf[1]:1
acRecvBuf[2]:2
acRecvBuf[3]:2

2、流式传输模式实现——本地进程间通信(AF_UNIX):

(1)代码实现:[root@localhost socket_stream]# cat stream.c

#include 
#include 
#include 
#include 
#include 

int main(void)
{
	int i =  0;
	pid_t stPid = {0};
	char acSendBuf[2] = {0};
	char acRecvBuf[4] = {0};

	stPid = fork();
	if(0 == stPid)
	{	
		struct sockaddr_un stAddr = {0};
		int iNewFD = 0;
		int iRecvFD = socket(AF_UNIX, SOCK_STREAM, 0);
		if(0 > iRecvFD)
		{
			printf("子进程打开socket\n");
			
		}

		remove("./.xx");
		stAddr.sun_family = AF_UNIX;
		sprintf(stAddr.sun_path, "./.xx");
		if(0 != bind(iRecvFD, (void *)&stAddr, sizeof(stAddr)))
		{
			printf("bind 失败!\n");
		}

		listen(iRecvFD, 1000);

		iNewFD = accept(iRecvFD, NULL, NULL);

		sleep(2);

		printf("\n接收的长度是%d\n",read(iNewFD, acRecvBuf, sizeof(acRecvBuf)));
		for(i = 0; i < sizeof(acRecvBuf); i++)
		{
			printf("acRecvBuf[%d]:%d\n", i, acRecvBuf[i]);
		}
	}
	else
	{
		sleep(1);
		struct sockaddr_un stAddr = {0};
		int iSendFD = socket(AF_UNIX, SOCK_STREAM, 0);
		if(0 > iSendFD)
		{
			printf("发送socket创建失败!\n");
			return 0;
		}
	
		stAddr.sun_family = AF_UNIX;
		sprintf(stAddr.sun_path, "./.xx");
		if(0 != connect(iSendFD, (void *)&stAddr, sizeof(stAddr)))
		{
			printf("连接失败!\n");
			return 0;
		}

		for(i = 0; i < 2; i++)
		{
			acSendBuf[0] = i + 1;
			acSendBuf[1] = i + 1;

			printf("发送长度是%d\n", write(iSendFD, acSendBuf, sizeof(acSendBuf)));
		}
	}

	return 0;
}

(2)编译执行:[root@localhost socket_stream]# make stream

(3)结果显示:

[root@localhost socket_stream]# ./stream
发送长度是2
发送长度是2
[root@localhost socket_stream]# 
接收的长度是4
acRecvBuf[0]:1
acRecvBuf[1]:1
acRecvBuf[2]:2
acRecvBuf[3]:2

3、报式传输模式实现——本地进程间通信(AF_UNIX):

(1)代码实现:[root@localhost socket_dgram]# cat dgram.c 

#include 
#include 
#include 
#include 
#include 

int main(void)
{
	int i =  0;
	pid_t stPid = {0};
	char acSendBuf[2] = {0};
	char acRecvBuf[4] = {0};

	stPid = fork();
	if(0 == stPid)
	{	
		struct sockaddr_un stAddr = {0};
		int iRecvFD = socket(AF_UNIX, SOCK_DGRAM, 0);
		if(0 > iRecvFD)
		{
			printf("子进程打开socket\n");
			
		}

		remove("./.xx");
		stAddr.sun_family = AF_UNIX;
		sprintf(stAddr.sun_path, "./.xx");
		if(0 != bind(iRecvFD, (void *)&stAddr, sizeof(stAddr)))
		{
			printf("bind 失败!\n");
		}

		sleep(2);

		printf("\n接收的长度是%d\n",recvfrom(iRecvFD, acRecvBuf, sizeof(acRecvBuf), 0, NULL, NULL));
		for(i = 0; i < sizeof(acRecvBuf); i++)
		{
			printf("acRecvBuf[%d]:%d\n", i, acRecvBuf[i]);
		}
	}
	else
	{
		sleep(1);
		struct sockaddr_un stAddr = {0};
		int iSendFD = socket(AF_UNIX, SOCK_DGRAM, 0);
		if(0 > iSendFD)
		{
			printf("发送socket创建失败!\n");
			return 0;
		}
	
		stAddr.sun_family = AF_UNIX;
		sprintf(stAddr.sun_path, "./.xx");

		for(i = 0; i < 2; i++)
		{
			acSendBuf[0] = i + 1;
			acSendBuf[1] = i + 1;

			printf("发送长度是%d\n", sendto(iSendFD, acSendBuf, sizeof(acSendBuf), 0, (void *)&stAddr, sizeof(stAddr)));
		}
	}

	return 0;
}

(2)编译执行:[root@localhost socket_dgram]# make dgram

(3)结果显示:

[root@localhost socket_dgram]# ./dgram
发送长度是2
发送长度是2
[root@localhost socket_dgram]# 
接收的长度是2
acRecvBuf[0]:1
acRecvBuf[1]:1
acRecvBuf[2]:0
acRecvBuf[3]:0

由上述代码对比可知,管道与流式传输两种方式得到的结果是一样的,fork出来的只是用来收,父进程用来发数据。
父进程每次发sizeof(acSendBuf),即,两个字节的大小,发两次,共 发送四个字节的大小;
而子进程每次都是用sizeof(acRecvBuf)四个字节来接收数据;
pipe模式与流式传输(socket_stream)两种方式都是,一次性全部四个字节,没有区分是第几次发送过来的数据;
而报式传输只收两个字节大小数据,即,第一个包的大小,若要收全部数据,需要循环接受。
所以综上所述,流式传输与类似于管道。

你可能感兴趣的:(C,语言,协议)