// 通过重叠网络(在本实验中,是一个TCP连接)接收STCP段. 我们建议你使用recv()一次接收一个字节. // 你需要查找"!&", 然后是seg_t, 最后是"!#". 这实际上需要你实现一个搜索的FSM, 可以考虑使用如下所示的FSM. // SEGSTART1 -- 起点 // SEGSTART2 -- 接收到'!', 期待'&' // SEGRECV -- 接收到'&', 开始接收数据 // SEGSTOP1 -- 接收到'!', 期待'#'以结束数据的接收 // 这里的假设是"!&"和"!#"不会出现在段的数据部分(虽然相当受限, 但实现会简单很多). // 你应该以字符的方式一次读取一个字节, 将数据部分拷贝到缓冲区中返回给调用者. // // 注意: 还有一种处理方式可以允许"!&"和"!#"出现在段首部或段的数据部分. 具体处理方式是首先确保读取到!&,然后 // 直接读取定长的STCP段首部, 不考虑其中的特殊字符, 然后按照首部中的长度读取段数据, 最后确保以!#结尾. // // 注意: 在你剖析了一个STCP段之后, 你需要调用seglost()来模拟网络中数据包的丢失. // 在sip_recvseg()的下面是seglost()的代码. // // 如果段丢失了, 就返回1, 否则返回0. // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // int sip_recvseg(int connection, seg_t* segPtr) { int state = 0,len=-1; char c; while(state == 0 || state == 1){ len = recv(connection,&c,sizeof(c),0); if (len <= 0){ printf("sip recv !& failed!%d\n",len); return 2; } if (state == 1) if (c == '&') state = 2; else if (c == '!') state = 1; else state = 0; else; if (state == 0) if (c == '!') state = 1; else printf("%c",c); } //printf("sip recv !& success!\n"); len = recv(connection,(char*)segPtr,sizeof(stcp_hdr_t),0); if (len < sizeof(stcp_hdr_t)){ printf("recv stcp_hdr_t failed!\n"); return 2; } state = 3; //printf("sip recv header success!\n"); int datalen = segPtr->header.length; len = recv(connection,(char*)(segPtr->data),datalen,0); if (len < datalen){ printf("recv stcp_data failed!\n"); return 2; } state = 4; //printf("sip recv data success!\n"); while(state == 4 || state == 5){ len = recv(connection,&c,sizeof(c),0); if (len <= 0){ printf("sip recv !# failed!\n"); return 2; } if (state == 5) if (c == '#') state = 6; else if (c == '!') state = 5; else state = 4; else; if (state == 4) if (c == '!') state = 5; } //printf("sip recv !# success!\n"); if (state == 6 && seglost() == 0) return 0; else{ printf("sip recv seglost.\n"); return 1; } }
//recv function int recvf(sendseg_arg_t *ptr, int connection) { char buf[sizeof(sendseg_arg_t) + 2]; char c; int idx = 0; // state can be 0,1,2,3; // 0 starting point // 1 '!' received // 2 '&' received, start receiving segment // 3 '!' received, // 4 '#' received, finish receiving segment int state = 0; while(recv(connection,&c,1,0)>0) { if (state == 0) { if(c=='!') state = 1; } else if(state == 1) { if(c=='&') state = 2; else state = 0; } else if(state == 2) { if(c=='!') { buf[idx]=c; idx++; state = 3; } else { buf[idx]=c; idx++; } } else if(state == 3) { if(c=='#') { buf[idx]=c; memcpy(ptr, buf, idx - 1); state = 0; idx = 0; //add segment error if(seglost(&ptr->seg)>0) { continue; } if(checkchecksum(&ptr->seg)<0) { printf("checksum error,drop!\n"); continue; } return 1; } else if(c=='!') { buf[idx]=c; idx++; } else { buf[idx]=c; idx++; state = 2; } } } return -1; }
//SRT process uses this function to receive a sendseg_arg_t structure which contains a segment and its src node ID from the SNP process. //Parameter network_conn is the TCP descriptor of the connection between the SRT process and the SNP process. //When a segment is received, use seglost to determine if the segment should be discarded, also check the checksum. //Return 1 if a sendseg_arg_t is succefully received, otherwise return -1. int snp_recvseg(int network_conn, int* src_nodeID, seg_t* segPtr) { char buf[sizeof(sendseg_arg_t)+2]; char c; int idx = 0; // state can be 0,1,2,3; // 0 starting point // 1 '!' received // 2 '&' received, start receiving segment // 3 '!' received, // 4 '#' received, finish receiving segment int state = 0; sendseg_arg_t *sendSegArg = (sendseg_arg_t *)malloc(sizeof(sendseg_arg_t)); // puts("in getsegToSend"); while(recv(network_conn,&c,1,0)>0) { if (state == 0) { if(c=='!') state = 1; } else if(state == 1) { if(c=='&') state = 2; else state = 0; } else if(state == 2) { if(c=='!') { buf[idx]=c; idx++; state = 3; } else { buf[idx]=c; idx++; } } else if(state == 3) { if(c=='#') { buf[idx]=c; idx++; memcpy(sendSegArg, buf, idx - 2); *src_nodeID = sendSegArg->nodeID; // printf("in getpktToSend, nextNodeID is %d\n", *nextNode); *segPtr = sendSegArg->seg; state = 0; idx = 0; if(seglost(segPtr)>0) { printf("seg lost!\n"); continue; } if(checkchecksum(segPtr)<0) { printf("checksum error, drop!\n"); continue; } free(sendSegArg); return 1; } else if(c=='!') { buf[idx]=c; idx++; } else { buf[idx]=c; idx++; state = 2; } } } free(sendSegArg); return -1; }