使用tcp流式套接字,tcp粘包是指傳送方傳送的若干包資料到接收方接
收時粘成一包,從接收緩衝區看,後一包資料的頭緊接著前一包資料的尾。
出現粘包現象的原因是多方面的,它既可能由傳送方造成,也可能由接
收方造成。傳送方引起的粘包是由tcp協議本身造成的,tcp為提高傳輸效率,
傳送方往往要收集到足夠多的資料後才傳送一包資料。若連續幾次傳送的數
據都很少,通常tcp會根據優化演算法把這些資料合成一包後一次傳送出去,
這樣接收方就收到了粘包資料。出現這種情況的原因是tcp協議採用了著名
的nagle演算法,這種演算法的策略就是把盡量把小的資料報拼接起來傳送,目的
是減少傳送方的系統開銷。
接收方引起的粘包是由於接收方使用者程序不及時接收資料,從而導致粘
包現象。這是因為接收方先把收到的資料放在系統接收緩衝區,使用者程序從
該緩衝區取資料,若下一包資料到達時前一包資料尚未被使用者程序取走,則
下一包資料放到系統接收緩衝區時就接到前一包資料之後,而使用者程序根據
預先設定的緩衝區大小從系統接收緩衝區取資料,這樣就一次取到了多包數
據。 如果網路速率較快的話,建議作乙個高效的協議,從接收端把資料劃分
開來,這是比較普遍的做法。但是如果網路本身較慢,可以關閉nagle演算法。
關於協議的問題以後再討論,這裡介紹關閉nagle演算法的方法:
socket sock;
const int bnodelay = 1;
sock = socket(af_inet,sock_stream,ipproto_tcp);
setsockopt(sock ,ipproto_tcp,tcp_nodelay,(char *)&bnodelay,sizeof(bnodelay));
echocli.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define err_exit(m) \
do \
while(0)
struct packet
;ssize_t readn(int fd, void *buf, size_t count)
else if (nread == 0)
return count - nleft;
bufp += nread;
nleft -= nread;
}return count;
}ssize_t writen(int fd, const void *buf, size_t count)
else if (nwritten == 0)
continue;
bufp += nwritten;
nleft -= nwritten;
}return count;
}int main(void)
n = ntohl(recvbuf.len);
ret = readn(sock, recvbuf.buf, n);
if (ret == -1)
err_exit("read");
else if (ret < n)
fputs(recvbuf.buf, stdout);
memset(&sendbuf, 0, sizeof(sendbuf));
memset(&recvbuf, 0, sizeof(recvbuf));
}close(sock);
return 0;
}echosrv.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define err_exit(m) \
do \
while(0)
struct packet
;ssize_t readn(int fd, void *buf, size_t count)
else if (nread == 0)
return count - nleft;
bufp += nread;
nleft -= nread;
}return count;
}ssize_t writen(int fd, const void *buf, size_t count)
else if (nwritten == 0)
continue;
bufp += nwritten;
nleft -= nwritten;
}return count;
}void do_service(int conn)
n = ntohl(recvbuf.len);
ret = readn(conn, recvbuf.buf, n);
if (ret == -1)
err_exit("read");
else if (ret < n)
fputs(recvbuf.buf, stdout);
writen(conn, &recvbuf, 4+n);}}
int main(void)
else
close(conn);
}return 0;
}makefile:
.phony:clean all
cc=gcc
cflags=-wall -g
bin=echosrv echocli
all:$(bin)
%.o:%.c
$(cc) $(cflags) -c $< -o $@
clean:
rm -f *.o $(bin)
用AddView和DeleteView實現多視
下面是關於cdocument addview和cdocument removeview的簡單介紹,具體請參見聯機文件 void cdocument addview cview pview 為當前cdocument類例項加入新的檢視。其中引數pview是指向新檢視的指標。void cdocument ...
android AsyncTask 請求與實現
asynctask是對thread和handler進行了封裝,這個封裝的讓我們在進行耗時的操作的時候不用自己啟動執行緒,可以在其類中進行相應的ui更新,這樣大大節約了時間,public class myasynctask extends asynctask 這種使用類泛型的方式進行內部資料的約定,在...
OpenRest nginx lua安裝與例項
1 安裝依賴 make install3 安裝lua依賴 apt get install m4 tar vxzf nettle 3.3.tar.gz cd nettle 3.3 configure make make install4 安裝lua及lua socket tar vxzf lua 5....