void *seghandler(void* arg) { int i; seg_t* seg=malloc(sizeof(seg_t)); client_tcb_t *t=NULL; while(1) { i=sip_recvseg(son_conn,seg); if(i<0)continue; //this seg lost printf("receive a seg dest:%d type ack: %d\n",seg->header.dest_port,seg->header.ack_num); t=NULL; for(i=0;i<MAX_TRANSPORT_CONNECTIONS;i++) { if(TCBTable[i]!=NULL&&TCBTable[i]->server_portNum==seg->header.src_port&&TCBTable[i]->client_portNum==seg->header.dest_port){ t=TCBTable[i]; break; } } if(t==NULL)continue; switch(t->state) { case CLOSED:break; case SYNSENT:if(seg->header.ack_num==t->next_seqNum&&seg->header.type==SYNACK) t->state=CONNECTED; break; case CONNECTED:break; case FINWAIT:if(seg->header.ack_num==t->next_seqNum&&seg->header.type==FINACK) t->state=CLOSED; } } return 0; }
void *seghandler(void* arg) { int rslt; seg_t* seg=(seg_t *)malloc(sizeof(seg_t)); while(1) { memset(seg, 0, sizeof(seg_t)); rslt=sip_recvseg(connection, seg); if(rslt==0) { int i = 0; for(i=0;i<MAX_TRANSPORT_CONNECTIONS;i++) { if(client_tcb_table[i]!=NULL){ if(client_tcb_table[i]->client_portNum == seg->header.dest_port){ //printf("======= i = %d ========\n", i); break; } } } if(i == MAX_TRANSPORT_CONNECTIONS) { printf("TCB ERROR!\n"); } switch(client_tcb_table[i]-> state) { case CLOSED: { printf("State: CLOSED\n"); printf("---------------------------------\n"); } break; case SYNSENT: { printf("State: SYNSENT\n"); printf("---------------------------------\n"); if(seg->header.type==SYNACK){ client_tcb_table[i]->state=CONNECTED; } } break; case CONNECTED: { printf("State: CONNECTED\n"); printf("---------------------------------\n"); } break; case FINWAIT: { printf("State: FINWAIT\n"); printf("---------------------------------\n"); if(seg->header.type==FINACK) client_tcb_table[i]->state=CLOSED; } break; default: break; } } else if(rslt < 0){ printf("Recv Error!\n"); break; } } return 0; }
void *seghandler(void* arg) { seg_t recvbuffer; while(1) { int temp = sip_recvseg(tcp_conn,&recvbuffer); if (temp == 0) { //printf("recv buffer\n"); handle(&recvbuffer); }else { if (temp == 2) { printf("RECV ERROR!\n"); exit(0); }else; } } return 0; }
// 这是由stcp_server_init()启动的线程. 它处理所有来自客户端的进入数据. seghandler被设计为一个调用sip_recvseg()的无穷循环, // 如果sip_recvseg()失败, 则说明重叠网络连接已关闭, 线程将终止. 根据STCP段到达时连接所处的状态, 可以采取不同的动作. // 请查看服务端FSM以了解更多细节. // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // void* seghandler(void* arg) { server_tcb_t *recv_tcb = NULL; seg_t *seg = (seg_t *)malloc(sizeof(seg_t)); seg_t *seg_ack = (seg_t *)malloc(sizeof(seg_t)); while(1) { recv_tcb = NULL; memset(seg, 0, sizeof(seg_t)); memset(seg_ack, 0, sizeof(seg_t)); int n = sip_recvseg(global_conn, seg); if(n == 2) { //printf("Seg lost!\n"); printf("---------------------------------\n"); continue; } else if(n == 0) { //judge checksum first! if(checkchecksum(seg) == -1) { printf("Error checksum!\n"); printf("---------------------------------\n"); continue; } //printf("Receive a seg!\n"); int i = 0; int port = seg->header.dest_port; for(i=0; i<MAX_TRANSPORT_CONNECTIONS; i++) { if(server_tcb_table[i]->server_portNum == port) break; } recv_tcb = server_tcb_table[i]; if(recv_tcb == NULL || i == MAX_TRANSPORT_CONNECTIONS) { perror("Server tcb table error!\n"); exit(-1); } switch(recv_tcb->state) { case CLOSED: { printf("State: CLOSED\n"); printf("---------------------------------\n"); } break; case LISTENING: { printf("State: LISTENING\n"); printf("---------------------------------\n"); if(seg->header.type == SYN) { recv_tcb->client_portNum = seg->header.src_port; recv_tcb->expect_seqNum = seg->header.seq_num; sendAck(seg, seg_ack, recv_tcb, SYNACK); recv_tcb->state = CONNECTED; } } break; case CONNECTED: { //printf("State: CONNECTED\n"); //printf("---------------------------------\n"); if(seg->header.type == SYN) { printf("State: CONNECTED -> SYN\n"); recv_tcb->client_portNum = seg->header.src_port; recv_tcb->expect_seqNum = seg->header.seq_num; sendAck(seg, seg_ack, recv_tcb, SYNACK); recv_tcb->state = CONNECTED; } else if(seg->header.type == FIN ) { printf("State: CONNECTED -> FIN\n"); if(recv_tcb->expect_seqNum == seg->header.seq_num) { sendAck(seg, seg_ack, recv_tcb, FINACK); recv_tcb->state = CLOSEWAIT; } else { printf("FIN Seq error!\n"); } } else if(seg->header.type == DATA) { printf("State: CONNECTED -> DATA\n"); //judge seq num printf("from port: %d to port %d, seq = %d, expected: %d\n", seg->header.src_port, seg->header.dest_port, seg->header.seq_num, recv_tcb->expect_seqNum); if(recv_tcb->expect_seqNum == seg->header.seq_num) { pthread_mutex_lock(recv_tcb->bufMutex); printf("data length: %d\n", seg->header.length); memcpy(recv_tcb->recvBuf+recv_tcb->usedBufLen, seg->data, seg->header.length); /* int i= 0; printf("\nin data recv-----------\n"); for(i = 0; i<seg->header.length; i++) { printf("%c", (char *)(recv_tcb->recvBuf)[i]); } printf("\n-----------\n"); */ /* printf("\n-------------\n usedbuflen: %d\n---------------\n",recv_tcb->usedBufLen); * */ recv_tcb->usedBufLen += seg->header.length; /* printf("\n-------------\n usedbuflen: %d\n----------------\n",recv_tcb->usedBufLen); * */ recv_tcb->expect_seqNum += seg->header.length; //recv_tcb->expect_seqNum %= MAX_SEG_LEN; //printf("\n+++++++++---------\nrecv_tcb->expect_seqNum = %d\n\n", recv_tcb->expect_seqNum); pthread_mutex_unlock(recv_tcb->bufMutex); sendAck(seg, seg_ack, recv_tcb, DATAACK); } else { printf("DATA Seq error!\n"); seg_ack->header.type = DATAACK; seg_ack->header.src_port = seg->header.dest_port; seg_ack->header.dest_port = seg->header.src_port; seg_ack->header.seq_num = 0; seg_ack->header.ack_num = recv_tcb->expect_seqNum; seg_ack->header.length = 0; seg_ack->header.rcv_win=0; seg_ack->header.checksum = 0; seg_ack->header.checksum = checksum(seg_ack); sip_sendseg(global_conn, seg_ack); } } } break; case CLOSEWAIT: { printf("State: CLOSEWAIT\n"); printf("---------------------------------\n"); if(seg->header.type == FIN) { sendAck(seg, seg_ack, recv_tcb, FINACK); recv_tcb->state = CLOSEWAIT; } } break; default: break; } } else if(n == 1) { continue; } } return 0; }
// 这是由stcp_client_init()启动的线程. 它处理所有来自服务器的进入段. // seghandler被设计为一个调用sip_recvseg()的无穷循环. 如果sip_recvseg()失败, 则说明重叠网络连接已关闭, // 线程将终止. 根据STCP段到达时连接所处的状态, 可以采取不同的动作. 请查看客户端FSM以了解更多细节. // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // void *seghandler(void* arg) { seg_t recvbuf; int i = 0, n; while(1){ if( (n = sip_recvseg(sipfd, &recvbuf)) == 0){ for(i = 0; i <MAX_TRANSPORT_CONNECTIONS ; i++){ if(tcb[i] != NULL && tcb[i]->client_portNum == recvbuf.header.dest_port && tcb[i]->server_portNum == recvbuf.header.src_port){ if(tcb[i]->state == SYNSENT && recvbuf.header.type == SYNACK){ printf("client port %d receive SYNACK\n", tcb[i]->client_portNum); tcb[i]->state = CONNECTED; } //only recv DATAACK when connected if(tcb[i]->state == CONNECTED && recvbuf.header.type == DATAACK){ int ack = recvbuf.header.ack_num; printf("client port %d receive DATAACK %d\n", tcb[i]->client_portNum, ack); pthread_mutex_lock(tcb[i]->bufMutex); assert(tcb[i]->sendBufHead != NULL); int num = tcb[i]->sendBufHead->seg.header.seq_num; printf("unAck_segNum %d \n", tcb[i]->unAck_segNum); while(num < ack){ segBuf_t *tmp = tcb[i]->sendBufHead; tcb[i]->sendBufHead = tmp->next; printf("delete seg %d \n", tmp->seg.header.seq_num); free(tmp); tcb[i]->unAck_segNum--; printf("unAck_segNum -- %d\n", tcb[i]->unAck_segNum); if(tcb[i]->sendBufHead != NULL) num = tcb[i]->sendBufHead->seg.header.seq_num; else break; } while(tcb[i]->unAck_segNum < GBN_WINDOW && tcb[i]->sendBufunSent != NULL){ tcb[i]->sendBufunSent->sentTime = time(NULL); printf("client send DATA %d \n", tcb[i]->sendBufunSent->seg.header.seq_num); sip_sendseg(sipfd, &(tcb[i]->sendBufunSent->seg)); tcb[i]->sendBufunSent = tcb[i]->sendBufunSent->next; tcb[i]->unAck_segNum++; printf("unAck_segNum ++ %d\n", tcb[i]->unAck_segNum); } pthread_mutex_unlock(tcb[i]->bufMutex); } if(tcb[i]->state == FINWAIT && recvbuf.header.type == FINACK){ printf("---------client port %d receive FINACK-----------\n", tcb[i]->client_portNum); tcb[i]->state = CLOSED; } break; } } } else if(n == -1){ // printf("SON is closed\n"); pthread_exit(NULL); } } pthread_exit(NULL); }
// 这是由stcp_server_init()启动的线程. 它处理所有来自客户端的进入数据. seghandler被设计为一个调用sip_recvseg()的无穷循环, // 如果sip_recvseg()失败, 则说明到SIP进程的连接已关闭, 线程将终止. 根据STCP段到达时连接所处的状态, 可以采取不同的动作. // 请查看服务端FSM以了解更多细节. void* seghandler(void* arg) { long i; int flag; unsigned int client_port; seg_t* seg = (seg_t*)malloc(sizeof(seg_t)); int* src_nodeID = (int*)malloc(sizeof(int)); while (1) { flag = sip_recvseg(sip_conn, src_nodeID, seg);///////////////////////////////////注意src_nodeID的使用 if (flag == 1) {//报文丢失 printf("the stcp server does'n receive a segment! segment is lost!\n"); continue; } if (checkchecksum(seg) == -1) { printf("Checksum error!\n"); continue; } if (flag == -1) {//接收不到报文,线程停止 printf("can't receive anything in tcp level, the seghandler thread is going to end.\n"); break; } for (i = 0; i < MAX_TRANSPORT_CONNECTIONS; i++) { if ((NULL != server_tcb[i]) && (server_tcb[i]->server_portNum == seg->header.dest_port) && (server_tcb[i]->client_portNum == seg->header.src_port) && (*src_nodeID == server_tcb[i]->client_nodeID)) { break; } } if (i == MAX_TRANSPORT_CONNECTIONS) { printf("the tcb you want to find does't exist! but...\n"); if (seg->header.type == SYN) { for (i = 0; i < MAX_TRANSPORT_CONNECTIONS; i++) { if ((NULL != server_tcb[i]) && (server_tcb[i]->server_portNum == seg->header.dest_port)) { break; } } if (i == MAX_TRANSPORT_CONNECTIONS) { printf("the tcb you want does't exist really!!\n"); continue; } } else continue; } switch (seg->header.type) { case 0: printf("the type stcp server receives is SYN\n"); break; case 1: printf("the type stcp server receives is SYNACK\n"); break; case 2: printf("the type stcp server receives is FIN\n"); break; case 3: printf("the type stcp server receives is FINACK\n"); break; case 4: printf("the type stcp server receives is DATA\n"); break; case 5: printf("the type stcp server receives is DATAACK\n"); break; } client_port = seg->header.src_port; switch (server_tcb[i]->state) { case CLOSED: printf("stcp server now is in CLOSED state!\n"); break; case LISTENING: printf("stcp server now is in LISTENING state!\n"); if (seg->header.type == SYN) { printf("receive a SYN!\n"); server_tcb[i]->state = CONNECTED; server_tcb[i]->client_portNum = seg->header.src_port; server_tcb[i]->client_nodeID = *src_nodeID; sendACK(i, client_port, *src_nodeID, SYNACK, seg); } break; case CONNECTED: printf("stcp server now is in CONNECTED state!\n"); if (seg->header.type == SYN) { printf("receive a SYN!\n"); server_tcb[i]->state = CONNECTED; server_tcb[i]->expect_seqNum = seg->header.seq_num; sendACK(i, client_port, *src_nodeID, SYNACK, seg); } else if (seg->header.type == FIN) { printf("receive a FIN!\n"); server_tcb[i]->state = CLOSEWAIT; sendACK(i, client_port, *src_nodeID, FINACK, seg); pthread_t FINhandle_thread; int rc; rc = pthread_create(&FINhandle_thread, NULL, FINhandler, (void *)i); if (rc) { printf("ERROR; return code from pthread_create() is %d\n", rc); exit(-1); } } else if (seg->header.type == DATA) { printf("receive a DATA!\n"); printf("the expect_seqNum is %d\n", server_tcb[i]->expect_seqNum); printf("the seqNum is %d\n", seg->header.seq_num); if (seg->header.seq_num == server_tcb[i]->expect_seqNum) { printf("the expect_seqNum == seq_num!\n"); pthread_mutex_lock(server_tcb[i]->bufMutex); memcpy(server_tcb[i]->recvBuf + server_tcb[i]->usedBufLen, seg->data, seg->header.length); printf("the seg->header.length is %d\n", seg->header.length); server_tcb[i]->usedBufLen += seg->header.length; server_tcb[i]->expect_seqNum += seg->header.length; seg->header.src_port = server_tcb[i]->server_portNum; //源端口号 seg->header.dest_port = client_port; //目的端口号 seg->header.seq_num = 0; //序号 seg->header.ack_num = server_tcb[i]->expect_seqNum; //确认号 seg->header.length = 0; //段数据长度 seg->header.type = DATAACK; //段类型 seg->header.rcv_win = 0; //当前未使用 seg->header.checksum = 0; seg->header.checksum = checksum(seg); //这个段的校验和 sip_sendseg(sip_conn, *src_nodeID, seg); printf("stcp server send the changing DATAACK %d succesfully!\n", seg->header.ack_num); pthread_mutex_unlock(server_tcb[i]->bufMutex); } else { printf("the expect_seqNum != seq_num!\n"); seg->header.src_port = server_tcb[i]->server_portNum; //源端口号 seg->header.dest_port = client_port; //目的端口号 seg->header.seq_num = 0; //序号 seg->header.ack_num = server_tcb[i]->expect_seqNum; //确认号 seg->header.length = 0; //段数据长度 seg->header.type = DATAACK; //段类型 seg->header.rcv_win = 0; //当前未使用 seg->header.checksum = 0; seg->header.checksum = checksum(seg); //这个段的校验和 sip_sendseg(sip_conn, *src_nodeID, seg); printf("stcp server send the not changed DATAACK %d succesfully!\n", seg->header.ack_num); } } break; case CLOSEWAIT: printf("stcp server now is in CLOSEWAIT state!\n"); if (seg->header.type == FIN) { printf("receive a FIN!\n"); sendACK(i, client_port, *src_nodeID, FINACK, seg); } break; } } return 0; }
void *seghandler(void* arg) { seg_t tmp; int src_node; while (1){ int k = sip_recvseg(sip_connfd, &src_node, &tmp); print_pos(); printf("sip_recvseg = %d\n", k); if( k == -1) { // usleep(100000); printf("\t\t\tWARNING: I lost a package\n"); } else if (k == 2){ sleep(1); // printf("unknown error\n"); } else { switch(tmp.header.type){ case SYN: printf("\t\t\t\tRECV SYN, client:%d server:%d\n", tmp.header.src_port, tmp.header.dest_port); break; case FIN: printf("\t\t\t\tRECV FIN, client:%d server:%d\n", tmp.header.src_port, tmp.header.dest_port); break; case DATA: printf("\t\t\t\tRECV DATA, client:%d server:%d\n", tmp.header.src_port, tmp.header.dest_port); break; default: break; } int i = 0, k = -1; for (i = 0; i < MAX_TRANSPORT_CONNECTIONS; i++) { if (tcb[i] != NULL) { if (tcb[i]->server_portNum == tmp.header.dest_port) { // 3种正常情况 if (tmp.header.type == SYN && tcb[i]->state == LISTENING){ printf("\tGOOD MSG: package right case 1: recv SYN\n"); k = i; break; } if (tmp.header.type == DATA && tcb[i]->state == CONNECTED && tmp.header.src_port == tcb[i]->client_portNum){ printf("\tGOOD MSG: package right case 2: recv DATA\n"); k = i; break; } if (tmp.header.type == FIN && tcb[i]->state == CONNECTED && tmp.header.src_port == tcb[i]->client_portNum){ printf("\tGOOD MSG: package right case 3: recv FIN\n"); k = i; break; } // 错误情况2种 if (tmp.header.type == SYN && tcb[i]->state == CONNECTED && tcb[i]->client_portNum == tmp.header.src_port){ printf("PACKAGE ERROR: error case 1: recv SYN when CONNECTED\n"); printf("\tERROR MSG: socket:%d client:%d server:%d\n", i, tcb[i]->client_portNum, tcb[i]->server_portNum); k = i; break; } if (tmp.header.type == FIN && tcb[i]->state == CLOSEWAIT && tcb[i]->client_portNum == tmp.header.src_port){ printf("PACKAGE ERROR: error case 2: recv FIN when CLOSEWAIT\n"); printf("\tERROR MSG: socket:%d client:%d server:%d\n", i, tcb[i]->client_portNum, tcb[i]->server_portNum); k = i; break; } } } else continue; } if (k == -1) { printf("PACKAGE ERROR: no such connect 4 package\n"); printf("\tERROR MSG: package client:%d server:%d\n", tmp.header.src_port, tmp.header.dest_port); } else { switch(tcb[k]->state){ case CLOSED: break; case LISTENING: if (tmp.header.type == SYN) { tcb[k]->state = CONNECTED; tcb[k]->client_portNum = tmp.header.src_port; seg_t ack; ack.header.src_port = tmp.header.dest_port; ack.header.dest_port = tmp.header.src_port; ack.header.seq_num = tcb[k]->expect_seqNum; ack.header.ack_num = tmp.header.ack_num; ack.header.length = 0; ack.header.type = SYNACK; ack.header.rcv_win = 0; ack.header.checksum = 0; memset(ack.data, 0, MAX_SEG_LEN); ack.header.checksum = checksum(&ack); printf("\tGOOD MSG: send SYNACK port:%d -> port:%d, src_node=%d\n", ack.header.dest_port, ack.header.src_port, src_node); if (sip_sendseg(sip_connfd, src_node, &ack)) printf("\tGOOD MSG: send SYNACK ok\n"); else printf("SEND ERROR: send SYNACK failed\n"); } break; case CONNECTED: if (tmp.header.type == FIN){ tcb[k]->state = CLOSEWAIT; tcb[k]->wait_start = clock(); seg_t ack; ack.header.src_port = tmp.header.dest_port; ack.header.dest_port = tmp.header.src_port; ack.header.seq_num = tcb[k]->expect_seqNum; ack.header.ack_num = tmp.header.ack_num; ack.header.length = 0; ack.header.type = FINACK; ack.header.rcv_win = 0; ack.header.checksum = 0; memset(ack.data, 0, MAX_SEG_LEN); ack.header.checksum = checksum(&ack); printf("\tGOOD MSG: send SYNACK port:%d -> port:%d, src_node=%d\n", ack.header.dest_port, ack.header.src_port, src_node); if (sip_sendseg(sip_connfd, src_node, &ack)) printf("\tGOOD MSG: send FINACK ok\n"); else printf("SEND ERROR: send FINACK failed\n"); } else if (tmp.header.type == DATA){ int ackNum = -1; if (tcb[k]->expect_seqNum == tmp.header.seq_num){ //是我想收的序号 if (tcb[k]->usedBufLen+tmp.header.length < RECEIVE_BUF_SIZE){//缓冲区未满 // printf("MSG: RECV data \'%s\'\n", tmp.data); pthread_mutex_lock(tcb[k]->bufMutex); memcpy(tcb[k]->recvBuf+tcb[k]->usedBufLen, tmp.data, tmp.header.length); tcb[k]->expect_seqNum = tcb[k]->expect_seqNum+tmp.header.length; tcb[k]->usedBufLen += tmp.header.length; pthread_mutex_unlock(tcb[k]->bufMutex); ackNum = tcb[k]->expect_seqNum; } } seg_t ack; ack.header.src_port = tmp.header.dest_port; ack.header.dest_port = tmp.header.src_port; ack.header.seq_num = tcb[k]->expect_seqNum; ack.header.ack_num = tmp.header.seq_num; ack.header.length = 0; ack.header.type = DATAACK; ack.header.rcv_win = 0; ack.header.checksum = 0; memset(ack.data, 0, MAX_SEG_LEN); ack.header.checksum = checksum(&ack); printf("MSG: recv seq_num %d, send ack_num %d\n", tmp.header.seq_num, ack.header.ack_num); printf("MSG: RECV data length %d\n", tmp.header.length); if (ackNum == -1) printf("DATA ERROR: expect %d, but recv %d\n", tcb[k]->expect_seqNum, tmp.header.seq_num); else printf("\tGOOD MSG: recv data right seq:%d\n", tmp.header.seq_num); printf("\tGOOD MSG: send DATAACK 4 client:%d -> server:%d\n", ack.header.dest_port, ack.header.src_port); if (sip_sendseg(sip_connfd, src_node, &ack)) printf("\tGOOD MSG: send DATAACK ok\n"); else printf("SEND ERROR: send DATAACK failed\n"); } else if (tmp.header.type == SYN){ seg_t ack; ack.header.src_port = tmp.header.dest_port; ack.header.dest_port = tmp.header.src_port; ack.header.seq_num = tcb[k]->expect_seqNum; ack.header.ack_num = tmp.header.ack_num; ack.header.length = 0; ack.header.type = SYNACK; ack.header.rcv_win = 0; ack.header.checksum = 0; memset(ack.data, 0, MAX_SEG_LEN); ack.header.checksum = checksum(&ack); printf("SEND ERROR: SYNACK lost\n"); printf("\tGOOD MSG: send SYNACK 4 client:%d -> server:%d\n", ack.header.dest_port, ack.header.src_port); if (sip_sendseg(sip_connfd, src_node, &ack)) printf("\tGOOD MSG: send SYNACK ok\n"); else printf("SEND ERROR: send SYNACK failed\n"); } break; case CLOSEWAIT: if (tmp.header.type == FIN){ tcb[k]->wait_start = clock(); seg_t ack; ack.header.src_port = tmp.header.dest_port; ack.header.dest_port = tmp.header.src_port; ack.header.seq_num = tcb[k]->expect_seqNum; ack.header.ack_num = tmp.header.ack_num; ack.header.length = 0; ack.header.type = FINACK; ack.header.rcv_win = 0; ack.header.checksum = 0; memset(ack.data, 0, MAX_SEG_LEN); ack.header.checksum = checksum(&ack); printf("SEND ERROR: FINACK lost\n"); printf("\tGOOD MSG: send FINACK 4 client:%d -> server:%d\n", ack.header.dest_port, ack.header.src_port); if (sip_sendseg(sip_connfd, src_node, &ack)) printf("\tGOOD MSG: send FINACK ok\n"); else printf("SEND ERROR: send FINACK failed\n"); } break; default: break; } } } } return 0; }
// 这是由stcp_client_init()启动的线程. 它处理所有来自服务器的进入段. // seghandler被设计为一个调用sip_recvseg()的无穷循环. 如果sip_recvseg()失败, 则说明到SIP进程的连接已关闭, // 线程将终止. 根据STCP段到达时连接所处的状态, 可以采取不同的动作. 请查看客户端FSM以了解更多细节. void* seghandler(void* arg) { int rslt; while(1) { int severNodeID; seg_t* seg=(seg_t *)malloc(sizeof(seg_t)); memset(seg, 0, sizeof(seg_t)); rslt=sip_recvseg(sip_conn, &severNodeID, seg); if(rslt < 0) { printf("Receive seg lost or error!\n"); continue; } if(checkchecksum(seg)==-1) { printf("Receive seg Checksum error\n"); continue; } if(rslt>0) { int i = 0; for(i=0;i<MAX_TRANSPORT_CONNECTIONS;i++) { if(client_tcb_table[i]!=NULL){ if(client_tcb_table[i]->client_portNum == seg->header.dest_port){ //printf("======= i = %d ========\n", i); break; } } } if(i == MAX_TRANSPORT_CONNECTIONS) { printf("TCB ERROR!\n"); continue; } client_tcb_t* recv_tcb = client_tcb_table[i]; switch(client_tcb_table[i]-> state) { case CLOSED: { printf("State: CLOSED\n"); //printf("---------------------------------\n"); } break; case SYNSENT: { printf("State: SYNSENT\n"); //printf("---------------------------------\n"); if(seg->header.type==SYNACK){ printf("recv SYNACK from server_port: %d\n", seg->header.src_port); client_tcb_table[i]->state=CONNECTED; } } break; case CONNECTED: if(seg->header.type == DATAACK) { printf("State: CONNECTED -> DATAACK\n"); pthread_mutex_lock(client_tcb_table[i]->bufMutex); //segBuf_t *phead = recv_tcb->sendBufHead; int ack = seg->header.ack_num; printf("ACK: %d\n", ack); // <=ack 的都被确认为收到,不需要再发送 if(recv_tcb->sendBufHead!= NULL) { int n = ack - recv_tcb->sendBufHead->seg.header.seq_num; while(n > 0) { segBuf_t *phead = recv_tcb->sendBufHead; recv_tcb->sendBufHead = phead->next; n -= phead->seg.header.length; free(phead); recv_tcb->unAck_segNum--; if(recv_tcb->sendBufunSent != NULL) { printf("send data to server, seq: %d\n", recv_tcb->sendBufunSent->seg.header.seq_num); sip_sendseg(sip_conn, recv_tcb->server_nodeID, &(recv_tcb->sendBufunSent->seg)); struct timeval sentTime; gettimeofday(&sentTime, 0); recv_tcb->sendBufunSent->sentTime_usec = sentTime.tv_usec; client_tcb_table[i]->sendBufunSent->sentTime_sec = sentTime.tv_sec; recv_tcb->sendBufunSent= recv_tcb->sendBufunSent->next; recv_tcb->unAck_segNum++; } } } pthread_mutex_unlock(client_tcb_table[i]->bufMutex); } break; case FINWAIT: { if(seg->header.type == FINACK) { printf("recv FINACK from server_port: %d\n", seg->header.src_port); client_tcb_table[i]->state = CLOSED; } } break; default: break; } } free(seg); } return 0; }
void *seghandler(void* arg) { seg_t seg_data; segBuf_t* p; int i; int ack_num; int nodeID; while(sip_recvseg(sip_conn,&nodeID,&seg_data)!=-1){ i=0; unsigned int temp; while(tcbtable[i]!=NULL && tcbtable[i]->server_portNum!=seg_data.header.src_port && i<MAX_TRANSPORT_CONNECTIONS)i++; if(i >= MAX_TRANSPORT_CONNECTIONS) return; switch(seg_data.header.type){ case SYNACK: if(tcbtable[i]->state == SYNSENT) tcbtable[i]->state=CONNECTED; break; case FINACK: if(tcbtable[i]->state == FINWAIT) tcbtable[i]->state=CLOSED; break; case DATAACK: if(tcbtable[i]->state == CONNECTED){ p = tcbtable[i]->sendBufHead; ack_num = seg_data.header.ack_num; //释放空间 pthread_mutex_lock(tcbtable[i]->send_bufMutex); while(tcbtable[i]->unAck_segNum > 0 && p != NULL && p->seg.header.seq_num < ack_num ){ tcbtable[i]->sendBufHead = tcbtable[i]->sendBufHead->next; free(p); p = tcbtable[i]->sendBufHead; tcbtable[i]->unAck_segNum--; } pthread_mutex_unlock(tcbtable[i]->send_bufMutex); } break; case DATA: if(tcbtable[i]->state==CONNECTED) { if(seg_data.header.seq_num==tcbtable[i]->expect_seqNum) { int len=seg_data.header.length-sizeof(stcp_hdr_t); pthread_mutex_lock(tcbtable[i]->rec_bufMutex); memcpy((char *)tcbtable[i]->recvBuf+tcbtable[i]->usedBufLen,(char *)&seg_data.data,len); tcbtable[i]->usedBufLen+=len; tcbtable[i]->expect_seqNum+=len; pthread_mutex_unlock(tcbtable[i]->rec_bufMutex); } temp=seg_data.header.src_port; seg_data.header.src_port=seg_data.header.dest_port; seg_data.header.dest_port=temp; seg_data.header.type = DATAACK; seg_data.header.ack_num = tcbtable[i]->expect_seqNum; seg_data.header.checksum=0; seg_data.header.length=sizeof(stcp_hdr_t); seg_data.header.checksum=checksum(&seg_data); sip_sendseg(sip_conn,tcbtable[i]->server_nodeID,&seg_data); } break; default: printf("server wrong\n");break; } } return 0; }
// 这是由stcp_client_init()启动的线程. 它处理所有来自服务器的进入段. // seghandler被设计为一个调用sip_recvseg()的无穷循环. 如果sip_recvseg()失败, 则说明到SIP进程的连接已关闭, // 线程将终止. 根据STCP段到达时连接所处的状态, 可以采取不同的动作. 请查看客户端FSM以了解更多细节. void* seghandler(void* arg) { pthread_detach(pthread_self()); //modify seg_t recv_segment; int sockfd; int connection_state; int src_nodeID; while (true) { connection_state = sip_recvseg(sip_conn, &src_nodeID, &recv_segment); //the segment is lost if (connection_state == -1) { continue; } sockfd = stcp_get_sockfd(&recv_segment); client_tcb_t *tcb = client_tcb_table[sockfd]; assert(src_nodeID == tcb -> server_nodeID); //sockfd error if (sockfd == -1) { continue; } //SYNACK if (recv_segment.header.type == SYNACK) { if (tcb -> state == SYNSENT) { tcb -> state = CONNECTED; } } //FINACK if (recv_segment.header.type == FINACK) { if (tcb -> state == FINWAIT) { tcb -> state = CLOSED; } } //DATAACK if (recv_segment.header.type == DATAACK) { if(tcb -> state == CONNECTED){ //printf("receive a dataack segment, ack %d\n", recv_segment.header.ack_num); int ack = recv_segment.header.ack_num; pthread_mutex_lock(tcb -> bufMutex); segBuf_t* bufhead = tcb -> sendBufHead; //ack segs those seq<ack while(bufhead -> seg.header.seq_num < ack){ tcb -> sendBufHead = tcb -> sendBufHead -> next; // printf("free segment in buf, seq %d\n", bufhead -> seg.header.seq_num); free(bufhead); bufhead = tcb -> sendBufHead; tcb -> unAck_segNum --; if(bufhead == NULL){ assert(tcb -> sendBufunSent == NULL); tcb -> sendBufTail = NULL; break; } } //send blocked segments(if exist) while(tcb -> sendBufunSent != NULL && tcb -> unAck_segNum < GBN_WINDOW){ sip_sendseg(sip_conn, tcb -> server_nodeID, &(tcb -> sendBufunSent -> seg)); printf("send a data segment, seq %d\n", (tcb -> sendBufunSent -> seg). header.seq_num); tcb -> sendBufunSent -> sentTime = get_time(); tcb -> unAck_segNum ++; tcb -> sendBufunSent = tcb -> sendBufunSent -> next; } pthread_mutex_unlock(tcb -> bufMutex); } } } }
// 这是由stcp_client_init()启动的线程. 它处理所有来自服务器的进入段. // seghandler被设计为一个调用sip_recvseg()的无穷循环. 如果sip_recvseg()失败, 则说明重叠网络连接已关闭, // 线程将终止. 根据STCP段到达时连接所处的状态, 可以采取不同的动作. 请查看客户端FSM以了解更多细节. // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // void *seghandler(void* arg) { int i; int flag; while (1) { seg_t* seg = (seg_t*)malloc(sizeof(seg_t)); flag = sip_recvseg(gSockFd, seg); if (flag == 1) {//报文丢失 printf("the stcp client does'n receive a segment! segment is lost!\n"); continue; } if (flag == -1) {//接收不到报文,线程停止 printf("can't receive anything in tcp level, the seghandler thread is going to end.\n"); break; } if (checkchecksum(seg) == -1) { printf("Checksum error!\n"); continue; } for (i = 0; i < client_tcb_size; i++) { if (NULL != client_tcb[i] && (client_tcb[i]->server_portNum == seg->header.src_port && client_tcb[i]->client_portNum == seg->header.dest_port)) { break; } } if (i == client_tcb_size) { printf("the tcb you want to find does't exist!\n"); continue; } printf("the type stcp client receives is %d\n", seg->header.type); switch (client_tcb[i]->state) { case CLOSED: printf("stcp client now is in CLOSED state!\n"); if (seg->header.type == SYN) { client_tcb[i]->state = SYNSENT; } break; case SYNSENT: printf("stcp client now is in SYNSENT state!\n"); if (seg->header.type == SYNACK) { printf("receive a SYNACK!\n"); client_tcb[i]->state = CONNECTED; } break; case CONNECTED: printf("stcp client now is in CONNECTED state!\n"); if (seg->header.type == DATAACK) { printf("receive a DATAACK %d!\n", seg->header.ack_num); pthread_mutex_lock(client_tcb[i]->bufMutex); segBuf_t *p = client_tcb[i]->sendBufHead; while (p != NULL && p != client_tcb[i]->sendBufunSent) { if (p->seg.header.seq_num < seg->header.ack_num) { client_tcb[i]->sendBufHead = p->next; printf("delete the %d seq_no\n", p->seg.header.seq_num); free(p); p = client_tcb[i]->sendBufHead; client_tcb[i]->unAck_segNum--; } else break;///////////////////////////////// } //不该重发 /*p = client_tcb[i]->sendBufHead; while (p != NULL && p != client_tcb[i]->sendBufunSent) {//重发,unAck_segNum不用加一 p->sentTime = getCurrentTime(); sip_sendseg(gSockFd, &(p->seg)); p = p->next; }*/ while((client_tcb[i]->unAck_segNum < GBN_WINDOW) && (client_tcb[i]->sendBufunSent != NULL)) { client_tcb[i]->sendBufunSent->sentTime = getCurrentTime(); sip_sendseg(gSockFd, &(client_tcb[i]->sendBufunSent->seg)); client_tcb[i]->sendBufunSent = client_tcb[i]->sendBufunSent->next; client_tcb[i]->unAck_segNum++; } pthread_mutex_unlock(client_tcb[i]->bufMutex); } break; case FINWAIT: printf("stcp client now is in FINWAIT state!\n"); if (seg->header.type == FINACK) { printf("receive a FINACK!\n"); client_tcb[i]->state = CLOSED; } break; } } return 0; }
void *seghandler(void* arg) { seg_t *segPtr = (seg_t*)malloc(sizeof(seg_t)); while (1) { int count = sip_recvseg(connection, segPtr); if ( count > 0) { unsigned short int type = segPtr->header.type; // 查找该数据段的TCB unsigned int client_port = segPtr->header.dest_port; int sockfd; for (sockfd = 0; sockfd < MAX_TRANSPORT_CONNECTIONS; sockfd ++) { if (tcb_table[sockfd] != NULL) { if (tcb_table[sockfd]->client_portNum == client_port) { break; } } } // client FSM switch(tcb_table[sockfd]->state) { case SYNSENT: if (type == SYNACK) { tcb_table[sockfd]->state = CONNECTED; printf("Client(SYNSENT): Get a SYNACK, state changes: SYNSENT---->CONNECTED\n"); } break; case CONNECTED: if (type == DATAACK) { int ack_num = segPtr->header.ack_num; // !!!!!!!!!!!!!!! printf("Client: Get a DATAACK from Server(expect_num is %d)\n", ack_num); pthread_mutex_lock(tcb_table[sockfd]->bufMutex); segBuf_t *q = tcb_table[sockfd]->sendBufHead; segBuf_t *p = NULL; while (q != tcb_table[sockfd]->sendBufunSent) { //释放发送缓冲区 if (q->seg.header.seq_num < ack_num) { p = q; q = q->next; free(p); } else break; } tcb_table[sockfd]->sendBufHead = q; // 发送数据段直到已发送但未被确认的段数量到达GBN_WINDOW为止 int ack_sum = 0; segBuf_t *q1 = tcb_table[sockfd]->sendBufHead; for (;q1 != tcb_table[sockfd]->sendBufunSent && q1 != NULL; q1 = q1->next) ack_sum ++; while (ack_sum < GBN_WINDOW) { if (tcb_table[sockfd]->sendBufunSent == NULL) break; printf("Client:send data to server(seq_num is %d)\n", tcb_table[sockfd]->sendBufunSent->seg.header.seq_num); sip_sendseg(connection, &tcb_table[sockfd]->sendBufunSent->seg); ack_sum ++; tcb_table[sockfd]->sendBufunSent = tcb_table[sockfd]->sendBufunSent->next; } //printf("ack_sum is %d-----------------------------\n", ack_sum); pthread_mutex_unlock(tcb_table[sockfd]->bufMutex); } break; case FINWAIT: if (type == FINACK) { tcb_table[sockfd]->state = CLOSED; printf("Client(FINWAIT): GET a FINACK, state changes: FINWAIT----->CLOSED\n"); } break; } } else if (count == 0); // 段数据丢失 else // TCP 连接断开 break; } free(segPtr); segPtr = NULL; pthread_exit(0); }