socket编程2——recv与send的一点理解测试

//PC间的通信测试recv与send函数,服务器端
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<arpa/inet.h>
#include<unistd.h>
#include <iostream>
#include<stdio.h>
#include <errno.h>
#include<stdio.h>
#include<stdlib.h>
#include<utility>
#include<string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/time.h>
using namespace std;
#define BUFF_LEN 1024
#define NUM_BUFF_LEN 10

const int port = 9000;
const int buffer =10;

int GetNum(int *sock);
void OnceText(int *sock);
void HandleText(int *sock,int num);
int WriteFile(char *buff,int num);
int main()
{
	struct sockaddr_in client_addr;
	struct sockaddr_in server_addr;
	
	int client_addr_size = sizeof(struct sockaddr_in);
	
	int server_sock,client_sock;
	server_sock = socket(AF_INET,SOCK_STREAM,0);
	if(-1==server_sock)
	{
		perror("socket");
		return -1;
	}
	printf("server_sock created\n");
	memset(&server_addr,0,sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	server_addr.sin_port = htons(port);
	
	if(-1 == bind(server_sock,(struct sockaddr *)&server_addr,sizeof(server_addr)))
	{
		perror("bind");
		return -1;
	}
	printf("bind finished\n");
	if(-1 == listen(server_sock,3))
	{
		perror("listen");
		return -1;
	}
	printf("listening\n");
	socklen_t client_addr_len = sizeof(client_addr);

	char *rec_buff = new char[BUFF_LEN];
	int rec_len=0;
	int send_len;
	const char *send_buffer = "send over";
	int num;

	while(1)
	{
		/*client_sock = accept(server_sock,(struct sockaddr *)&client_addr,&client_addr_len);	
		if(-1 == client_sock)
		{
			perror("accept");
			return -1;
		}
		printf("accept fineshed\n");
		int num = GetNum(&client_sock);
		printf("num=%d\r\n",num);
		HandleText(&client_sock,BUFF_LEN);
		*/
		client_sock = accept(server_sock,(struct sockaddr *)&client_addr,&client_addr_len);
		if(-1 == client_sock)
		{
			perror("accept");
			return -1;
		}
		cout<<"accept finished"<<endl;

		/*int num = GetNum(&client_sock);

				rec_len = recv(client_sock,rec_buff,BUFF_LEN,0);
				cout<<"rec_len="<<rec_len<<endl; 
				cout<<"rec_buff="<<rec_buff<<endl;
				WriteFile(rec_buff,strlen(rec_buff));
			while(rec_len == BUFF_LEN)
			{
				rec_len = recv(client_sock,rec_buff,BUFF_LEN,0);
				cout<<"rec_len="<<rec_len<<endl; 
				cout<<"rec_buff="<<rec_buff<<endl;
				WriteFile(rec_buff,strlen(rec_buff));
			}
		*/
		num = GetNum(&client_sock);

		send_len = send(client_sock,send_buffer,BUFF_LEN,0);
		cout<<"send over finished"<<endl;
		if(num <= BUFF_LEN)
			OnceText(&client_sock);
	}
	delete(rec_buff);
	//close(server_sock);
	return 0;
} 
int GetNum(int *sock)
{
	int client_sock = *sock;
	int rec_len;
	char *num_buff = new char[NUM_BUFF_LEN];
	rec_len = recv(client_sock,num_buff,NUM_BUFF_LEN,0);
	if((rec_len<0) &&(errno == EAGAIN||errno == EWOULDBLOCK||errno == EINTR))
		{
			printf("net error,continue receive");
			
		}
	else if(rec_len<0)
		{
			perror("NUM SOCKET_ERROR");
			return -1; 
		}
	return atoi(num_buff);
}
void OnceText(int *sock)
{
	int client_sock = *sock;
	char *rec_buff = new char[BUFF_LEN];
	int rec_len;

	rec_len = recv(client_sock,rec_buff,BUFF_LEN,0);
	if((rec_len<0) &&(errno == EAGAIN||errno == EWOULDBLOCK||errno == EINTR))
		{
			printf("net error,continue receive");
			
		}
	else if(rec_len<0)
		{
			perror("Once SOCKET_ERROR");
			return ; 
		}
	WriteFile(rec_buff,strlen(rec_buff));
}

void HandleText(int *sock,int num)
{
	int size = num;
	int client_sock = *sock;
	int rec_len;
	char rec_buff[BUFF_LEN];
	while(size>0)
	{	
		if(0==size/BUFF_LEN)
		rec_len = recv(client_sock,rec_buff,size,0);
		else
		rec_len = recv(client_sock,rec_buff,BUFF_LEN,0);
		if((rec_len<0) &&(errno == EAGAIN||errno == EWOULDBLOCK||errno == EINTR))
		{
			printf("net error,continue receive");
		}
		else if(rec_len<0)
		{
			perror("TEXT SOCKET_ERROR");
			return ; 
		}
		cout<<"rec_len="<<rec_len<<endl; 
		cout<<"rec_buff="<<rec_buff<<endl;
		WriteFile(rec_buff,rec_len);
			
		size = size - rec_len;
	}
	//char *c ;
	//c = "\n";
	//WriteFile(c,1);
	return ;
}
int WriteFile(char *buff,int num)
{
	cout<<"write begin"<<endl;
	FILE *f=NULL;
	//char *c = "\0";
	//*(buff+num-1) = *c;
	//cout<<"0 filled end"<<endl;
	//cout<<"buff="<<buff<<endl;	
	f = fopen("diary.txt","aw+");
	if(f==NULL)
		perror("file open");
	fprintf(f,"%s",buff);
	fprintf(f,"\n");
	fclose(f);
	return 1;
}

//客户端

这两函数具体的没找到很详细的资料,自己测试一下

想要知道recv与send的第三个count的参数的到底是怎么样工作的,是直接发送或者接收count,还是读缓存区最大count数量的内容发送等问题

因为想要在发送方通过输入的方式得到内容在发送出去,可能会输入的内容超出了缓存区大小,或者收发双方的缓存区不一样大,还有想法是把输入内容存到文件再另外读取发送,内种方法之后在做,试了一会了忘了记录了,现在开始记录吧

1.recv是会阻塞的

 

程序会阻塞在recv这里

 

2.似乎recv与send函数是会沟通的,

这次实验中send函数数目参数100的情况下,但是recv函数数目参数是10,这种情况下再继续调用recv函数就不会阻塞,还会一直读取buff,发送的内容10以内,所以后面内容是空的猜想应该是发送的buffer填充的字符数组后面是空的,但是仍然发送了,所以接收的内容是空,下一步试着用超过10的内容测试一下看看能不能两次recv收到完整的内容

 

 

 

3.发送100,内容超过10,接收10,试试能不能两次rev收到完整

结果来看,发送的七个la,接收一次不能接收完,但第二次接收还是两个lala,可以说是接收成功了,所以猜想成功,确实是把发送内边的buff后面内容继续读了最后还因为刚好发送数目跟接收数目成倍数,接收最后一次还是10阻塞了

4.发送15,  内存越界

内容超过10,所以应该会recv执行两次,并且不是倍数,也会成功跳出来,并成功

 

5. 试一试发送参数大于发送缓存会发生什么

很奇怪的,申请的缓存区5,但是输入超过5的内容依然可以写进去,然后正常发送,

 

发送1234567

发送123456789

所以发送的数据多少是由发送的参数决定的。

上面说的超过缓存区依然可以访问的问题属于内存越界,并不一定会程序崩溃,但是会带来风险。

https://blog.csdn.net/rain_qingtian/article/details/10093829

6结论

结论来说,想要安全的发送接收东西,最好就是执行一次发送,一次接收,接收的内容可以是整个缓存区,发送数目设置为字符串长度或者整个缓存区,(输入的字符串结尾会带\0)

针对要发送的内容可能超出缓存的情况,在做一次改进,还是先发送一次所有内容的数量,然后服务器端回发一次get信号,这样客户端可以阻塞在recv等待服务器处理得到数量以后,客户端再发送内容,就可以解决之前连着发送内容出错的情况。

或者,每次发送缓存区大小的内容,在里面再自订协议

 

猜你喜欢

转载自blog.csdn.net/zhangzhi2ma/article/details/82414612