在使用C socket編程過程中,需要注意數(shù)據(jù)的斷包和粘包問題。一般情況下,Json數(shù)據(jù)是以換行符號或空格作為結(jié)束標(biāo)志的,而socket傳輸?shù)臄?shù)據(jù)是沒有結(jié)束標(biāo)志的。
因此,在接收J(rèn)son數(shù)據(jù)時,需要設(shè)置緩沖區(qū)大小,通過比較接收到的數(shù)據(jù)長度和Json數(shù)據(jù)長度,來確認(rèn)是否接收完整。以下是接收J(rèn)son數(shù)據(jù)的示例代碼:
int recv_json(int sockfd, char* recvbuf, int recvlen) { int ret; int cur_len = 0; int total_len = 0; char* p = NULL; while(1) { ret = recv(sockfd, recvbuf + total_len, recvlen - total_len, 0); if(ret<= 0) { break; } total_len += ret; if(total_len >= recvlen) { break; } } if(total_len == 0) { return total_len; } if(total_len >= recvlen) { recvbuf[recvlen - 1] = '\0'; } //查找結(jié)束標(biāo)志 p = strstr(recvbuf, "\r\n"); if(p != NULL) { *p = '\0'; return strlen(recvbuf); } p = strstr(recvbuf, "\n"); if(p != NULL) { *p = '\0'; return strlen(recvbuf); } return 0; }
以上代碼在接收J(rèn)son數(shù)據(jù)時,通過不斷接收socket數(shù)據(jù),并累計(jì)收到的數(shù)據(jù)長度,判斷是否收到完整的Json數(shù)據(jù)。然后再查找結(jié)束標(biāo)志,將之前接收到的數(shù)據(jù)全部保存,并返回其長度。
另外,發(fā)送Json數(shù)據(jù)時,可以將數(shù)據(jù)長度作為前綴發(fā)送,接收方先接收前綴長度,再根據(jù)長度接收J(rèn)son數(shù)據(jù)。以下是發(fā)送Json數(shù)據(jù)的示例代碼:
int send_json(int sockfd, char* sendbuf, int sendlen) { char buf[1024] = {0}; sprintf(buf, "%d\n%s", sendlen, sendbuf); return send(sockfd, buf, strlen(buf), 0); }
以上代碼將Json數(shù)據(jù)長度與Json數(shù)據(jù)內(nèi)容拼接在一起,發(fā)送給對方。在接收方接收數(shù)據(jù)時,先接收長度,再根據(jù)長度接收J(rèn)son數(shù)據(jù)內(nèi)容。