//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等待服务器处理得到数量以后,客户端再发送内容,就可以解决之前连着发送内容出错的情况。
或者,每次发送缓存区大小的内容,在里面再自订协议