예제 #1
0
파일: seg.c 프로젝트: DC-Swind/SimpleNet
// 通过重叠网络(在本实验中,是一个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;
    }
}
예제 #2
0
//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;
}