之前写了一个python版本的 现在给上一个c的版本
需求:服务端 接收客户端数据存入到本地 数据包格式 包头前4个字节是一个int 解析出来指的是后面跟随的数据的大小 (字节数)
这里我们就要解析包头 存入数据
其实这个思路很简单 就是用socket接收4个字节 解析出int 数据包的大小为x 再去接收x个字节的数据存入到本地就可以了
注意: 由于网络可能会有延迟 recv不一定能完全接收到相应大小的数据 比如 要接收2000个数据 结果只接收了1900个 所以要写个循环判断不断接收到相应字节数为止 包头的那4个字节也要写相同的判断 虽然4个字节漏的概率很小 但是考虑到安全性
下面我给出的是c代码
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #define MYPORT 9999 #define QUEUE 20 #define BUFFER_SIZE 1024 #define HEAD_LEN 4 //函数提前声明 不然按编译器 要看调用解析顺序去排列函数位置 这样就避免了这个问题 int read_head_value(int conn); void read_data(int conn,int t,FILE *f); int main() { FILE *f = fopen("test.pcm","wa"); int packet_head = 0; //报头值 // char* packet_head_data = (char *)malloc(HEAD_LEN*sizeof(char)); ///定义sockfd int server_sockfd = socket(AF_INET,SOCK_STREAM, 0); ///定义sockaddr_in struct sockaddr_in server_sockaddr; server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_port = htons(MYPORT); server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); ///bind,成功返回0,出错返回-1 if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1) { perror("bind"); exit(1); } ///listen,成功返回0,出错返回-1 if(listen(server_sockfd,QUEUE) == -1) { perror("listen"); exit(1); } ///客户端套接字 // char buffer[BUFFER_SIZE]; struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); ///成功返回非负描述字,出错返回-1 int conn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length); if(conn<0) { perror("connect"); exit(1); } int t; // c 中没有 true 会报错 true 属于 C++ while(1){ t = read_head_value(conn); read_data(conn,t,f); } fclose(f); close(conn); close(server_sockfd); return 0; } // 用int解析报头 返回报头值 有返回值的函数不一定必须要有个参数来接收返回值 可以直接使用 比如 read_head_value(conn)直接使用是可以的 int read_head_value(int conn) { char *p = (char *)malloc(HEAD_LEN * sizeof(char)); int *q = p; int t; int len,add; len = recv(conn,p,HEAD_LEN,0); while(len < HEAD_LEN){ add = recv(conn,p,HEAD_LEN-len,0); len = len + add; } printf("len is %d\n",len); printf("packet head len is %d\n",*q); t = *q; free(q); // p释放了 也就是说q和p所指向的那块内存释放了 事实如果后面return *q 返回的结果为0 其实释放p,q都是释放那段内存空间 free(p)释放4个char free(q)释放1个int 在这个机器上是等价的 return t; } // 读取数据 recv 第二个参数是buffer 接收数据的字节数 void read_data(int conn,int t,FILE *f) { char *p = (char *)malloc(t * sizeof(char)); memset(p,0,t); //清空内存数据 防止数据出错 int len,add; len = recv(conn,p,t,0); printf("first get len is %d\n",len); fwrite(p,sizeof(char),len,f); while(len < t){ memset(p,0,t); //清空内存数据 防止数据出错 add = recv(conn,p,t-len,0); fwrite(p,sizeof(char),add,f); printf("add is %d\n",add); len = len + add; } printf("packet data len is %d\n",len); printf("the packet data first addr %d\n",p); free(p); }
c代码总感觉有时候会有奇妙的错误,望大家实时改进,指出不足。
浙公网安备 33010602011771号