讀Muduo原始碼筆記---3(ttcp分析)
阿新 • • 發佈:2018-11-04
1、ttcp作用:檢測TCP吞吐量
2、ttcp協議:
3、一次寫一定長度的資料
static int write_n(int sockfd, const void* buf, int length) { int written = 0; while (written < length) { ssize_t nw = ::write(sockfd, static_cast<const char*>(buf) + written, length - written); if (nw > 0) { written += static_cast<int>(nw); } else if (nw == 0) { break; // EOF } else if (errno != EINTR) { perror("write"); break; } } return written; }
4、一次讀一定長度的資料
static int read_n(int sockfd, void* buf, int length) { int nread = 0; while (nread < length) { ssize_t nr = ::read(sockfd, static_cast<char*>(buf) + nread, length - nread); if (nr > 0) { nread += static_cast<int>(nr); } else if (nr == 0) { break; // EOF } else if (errno != EINTR) { perror("read"); break; } } return nread; }
5、協議實現過程
//傳送端 //先發送SessionMessage,確定傳送資料的包數,以及每包大小 struct SessionMessage sessionMessage = { 0, 0 }; sessionMessage.number = htonl(opt.number); sessionMessage.length = htonl(opt.length); if (write_n(sockfd, &sessionMessage, sizeof(sessionMessage)) != sizeof(sessionMessage)) { perror("write SessionMessage"); exit(1); } //生成測試資料 const int total_len = static_cast<int>(sizeof(int32_t) + opt.length); PayloadMessage* payload = static_cast<PayloadMessage*>(::malloc(total_len)); assert(payload); payload->length = htonl(opt.length); for (int i = 0; i < opt.length; ++i) { payload->data[i] = "0123456789ABCDEF"[i % 16]; } //傳送資料 for (int i = 0; i < opt.number; ++i) { int nw = write_n(sockfd, payload, total_len); assert(nw == total_len); int ack = 0; int nr = read_n(sockfd, &ack, sizeof(ack));//資料傳送完,等待服務端回覆接收資料的長度 assert(nr == sizeof(ack)); ack = ntohl(ack); assert(ack == opt.length);//判斷資料長度是否滿足 } double elapsed = timeDifference(muduo::Timestamp::now(), start); printf("%.3f seconds\n%.3f MiB/s\n", elapsed, total_mb / elapsed); //最後記錄時間差,計算出吞吐量 //接收端---和客戶端一樣 //接收SessionMessage struct SessionMessage sessionMessage = { 0, 0 }; if (read_n(sockfd, &sessionMessage, sizeof(sessionMessage)) != sizeof(sessionMessage)) { perror("read SessionMessage"); exit(1); } //接收每一包 for (int i = 0; i < sessionMessage.number; ++i) { payload->length = 0; if (read_n(sockfd, &payload->length, sizeof(payload->length)) != sizeof(payload->length)) { perror("read length"); exit(1); } payload->length = ntohl(payload->length); assert(payload->length == sessionMessage.length); if (read_n(sockfd, payload->data, payload->length) != payload->length) { perror("read payload data"); exit(1); } int32_t ack = htonl(payload->length);//資料包長度 if (write_n(sockfd, &ack, sizeof(ack)) != sizeof(ack))//應答回覆接收到的資料包長度 { perror("write ack"); exit(1); } }