int main() { //用于丢包率的随机数种子 srand(time(NULL)); //启动重叠网络层并获取重叠网络层TCP套接字描述符 int son_conn = son_start(); if(son_conn<0) { printf("fail to start overlay network\n"); exit(1); } //初始化stcp客户端 stcp_client_init(son_conn); //在端口87上创建STCP客户端套接字, 并连接到STCP服务器端口88. int sockfd = stcp_client_sock(CLIENTPORT1); if(sockfd<0) { printf("fail to create stcp client sock"); exit(1); } if(stcp_client_connect(sockfd,SERVERPORT1)<0) { printf("fail to connect to stcp server\n"); exit(1); } printf("client connected to server, client port:%d, server port %d\n",CLIENTPORT1,SERVERPORT1); //获取sendthis.txt文件长度, 创建缓冲区并读取文件中的数据. FILE *f; f = fopen("sendthis.txt","r"); assert(f!=NULL); fseek(f,0,SEEK_END); int fileLen = ftell(f); fseek(f,0,SEEK_SET); char *buffer = (char*)malloc(fileLen); fread(buffer,fileLen,1,f); fclose(f); //首先发送文件长度, 然后发送整个文件. stcp_client_send(sockfd,&fileLen,sizeof(int)); stcp_client_send(sockfd, buffer, fileLen); free(buffer); //等待一段时间, 然后关闭连接. sleep(WAITTIME); if(stcp_client_disconnect(sockfd)<0) { printf("fail to disconnect from stcp server\n"); exit(1); } if(stcp_client_close(sockfd)<0) { printf("fail to close stcp client\n"); exit(1); } //停止重叠网络层 son_stop(son_conn); }
// 发送数据给STCP服务器. 这个函数使用套接字ID找到TCB表中的条目. // 然后它使用提供的数据创建segBuf, 将它附加到发送缓冲区链表中. // 如果发送缓冲区在插入数据之前为空, 一个名为sendbuf_timer的线程就会启动. // 每隔SENDBUF_ROLLING_INTERVAL时间查询发送缓冲区以检查是否有超时事件发生. // 这个函数在成功时返回1,否则返回-1. // stcp_client_send是一个非阻塞函数调用. // 因为用户数据被分片为固定大小的STCP段, 所以一次stcp_client_send调用可能会产生多个segBuf // 被添加到发送缓冲区链表中. 如果调用成功, 数据就被放入TCB发送缓冲区链表中, 根据滑动窗口的情况, // 数据可能被传输到网络中, 或在队列中等待传输. int stcp_client_send(int sockfd, void* data, unsigned int length) { if(length <= MAX_SEG_LEN){ client_tcb_t* tmp = tcbtable[sockfd]; seg_t tmpseg; tmpseg.header.src_port = tmp->client_portNum; tmpseg.header.dest_port = tmp->server_portNum; tmpseg.header.length = length+sizeof(stcp_hdr_t); tmpseg.header.type = DATA; tmpseg.header.seq_num = tmp->next_seqNum; tmpseg.header.ack_num = 0; tmpseg.header.rcv_win = 0; tmpseg.header.checksum = 0; memcpy(tmpseg.data, (char *)data,length); tmpseg.header.checksum = checksum(&tmpseg); segBuf_t* p = (segBuf_t*)malloc(sizeof(segBuf_t)); p->seg = tmpseg; p->sendTime = 0; p->next = NULL; pthread_mutex_lock(tmp->send_bufMutex); tmp->next_seqNum += length; if(tmp->sendBufHead == NULL){ tmp->sendBufHead = p; tmp->sendBufTail = p; tmp->sendBufunSend = p; //启动sendBuf_timer pthread_t phd; pthread_create(&phd,NULL,sendBuf_timer,(void*)tmp); //启动sendThread pthread_t phd2; pthread_create(&phd2,NULL,sendThread,(void*)tmp); } else{ tmp->sendBufTail->next = p; tmp->sendBufTail = p; if(tmp->sendBufunSend == NULL){//特殊情况,说明之前没有未发送的数据 tmp->sendBufunSend = p; } } pthread_mutex_unlock(tmp->send_bufMutex); } else{//最多MAX_SEG_LEN,大于的要 递归地分成两部分进行发送 char substr[MAX_SEG_LEN]; strncpy(substr, (char *)data, MAX_SEG_LEN); stcp_client_send(sockfd, (void *)substr, MAX_SEG_LEN); stcp_client_send(sockfd, (void *)((char *)data+MAX_SEG_LEN), length-MAX_SEG_LEN); } return 1; }
int main() { //用于丢包率的随机数种子 srand(time(NULL)); //连接到SIP进程并获得TCP套接字描述符 int sip_conn = connectToSIP(); if(sip_conn<0) { printf("fail to connect to the local SIP process\n"); exit(1); } //初始化stcp客户端 stcp_client_init(sip_conn); sleep(STARTDELAY); char hostname[50]; printf("Enter server name to connect:"); scanf("%s",hostname); int server_nodeID = topology_getNodeIDfromname(hostname); if(server_nodeID == -1) { printf("host name error!\n"); exit(1); } else { printf("connecting to node %d\n",server_nodeID); } //在端口87上创建STCP客户端套接字, 并连接到STCP服务器端口88. int sockfd = stcp_client_sock(CLIENTPORT1); if(sockfd<0) { printf("fail to create stcp client sock"); exit(1); } if(stcp_client_connect(sockfd,server_nodeID,SERVERPORT1)<0) { printf("fail to connect to stcp server\n"); exit(1); } printf("client connected to server, client port:%d, server port %d\n",CLIENTPORT1,SERVERPORT1); //获取sendthis.txt文件长度, 创建缓冲区并读取文件中的数据 FILE *f; f = fopen("sendthis.txt","r"); assert(f!=NULL); fseek(f,0,SEEK_END); int fileLen = ftell(f); fseek(f,0,SEEK_SET); char *buffer = (char*)malloc(fileLen); fread(buffer,fileLen,1,f); fclose(f); //首先发送文件长度, 然后发送整个文件. stcp_client_send(sockfd,&fileLen,sizeof(int)); stcp_client_send(sockfd, buffer, fileLen); free(buffer); //等待一段时间, 然后关闭连接. sleep(WAITTIME); if(stcp_client_disconnect(sockfd)<0) { printf("fail to disconnect from stcp server\n"); exit(1); } if(stcp_client_close(sockfd)<0) { printf("fail to close stcp client\n"); exit(1); } //断开与SIP进程之间的连接 disconnectToSIP(sip_conn); }
int main() { //用于丢包率的随机数种子 srand(time(NULL)); //连接到SIP进程并获得TCP套接字描述符 int sip_conn = connectToSIP(); if(sip_conn<0) { printf("can not connect to the local SIP process\n"); } //初始化STCP服务器 stcp_server_init(sip_conn); //启动seghandler线程 pthread_t seghandle_thread; int rc; rc = pthread_create(&seghandle_thread, NULL, seghandler, &sip_conn); if (rc) { printf("ERROR; return code from pthread_create() is %d\n", rc); exit(-1); } //在端口SERVERPORT1上创建STCP服务器套接字 int sockfd= stcp_server_sock(SERVERPORT1); if(sockfd<0) { printf("can't create stcp server\n"); exit(1); } //监听并接受来自STCP客户端的连接 stcp_server_accept(sockfd); char hostname[50]; printf("Enter server name to connect:"); scanf("%s",hostname); int server_nodeID = topology_getNodeIDfromname(hostname); if(server_nodeID == -1) { printf("host name error!\n"); exit(1); } else { printf("connecting to node %d\n",server_nodeID); } //在端口87上创建STCP客户端套接字, 并连接到STCP服务器端口88 int sockfd2 = stcp_client_sock(CLIENTPORT1); if(sockfd2<0) { printf("fail to create stcp client sock"); exit(1); } if(stcp_client_connect(sockfd2,server_nodeID,SERVERPORT1)<0) { printf("fail to connect to stcp server\n"); exit(1); } char buf1[6]; //接收来自第一个连接的字符串 int i; for(i=0;i<5;i++) { stcp_server_recv(sockfd,buf1,6); printf("recv string: %s from connection 1\n",buf1); } //通过第二个连接发送字符串 char mydata2[7] = "byebye"; for(i=0;i<5;i++){ stcp_client_send(sockfd2, mydata2, 7); printf("send string:%s to connection 2\n",mydata2); } sleep(WAITTIME); //关闭STCP服务器 if(stcp_server_close(sockfd)<0) { printf("can't destroy stcp server\n"); exit(1); } sleep(WAITTIME); //关闭连接 if(stcp_client_disconnect(sockfd2)<0) { printf("fail to disconnect from stcp server\n"); exit(1); } //断开与SIP进程之间的连接 disconnectToSIP(sip_conn); }
// 发送数据给STCP服务器. 这个函数使用套接字ID找到TCB表中的条目. // 然后它使用提供的数据创建segBuf, 将它附加到发送缓冲区链表中. // 如果发送缓冲区在插入数据之前为空, 一个名为sendbuf_timer的线程就会启动. // 每隔SENDBUF_ROLLING_INTERVAL时间查询发送缓冲区以检查是否有超时事件发生. // 这个函数在成功时返回1,否则返回-1. // stcp_client_send是一个非阻塞函数调用. // 因为用户数据被分片为固定大小的STCP段, 所以一次stcp_client_send调用可能会产生多个segBuf // 被添加到发送缓冲区链表中. 如果调用成功, 数据就被放入TCB发送缓冲区链表中, 根据滑动窗口的情况, // 数据可能被传输到网络中, 或在队列中等待传输. int stcp_client_send(int sockfd, void* data, unsigned int length) { if (sockfd < 0 || sockfd >= MAX_TRANSPORT_CONNECTIONS) return -1; client_tcb_t *tcb = client_tcb_table[sockfd]; if (tcb == NULL) return -1; if (tcb -> state != CONNECTED) return -1; // if length > MAX_SEG_LEN, data will be cut and send twice or more int real_length = (length > MAX_SEG_LEN) ? MAX_SEG_LEN : length; /*build a segbuf to contain new segment*/ segBuf_t* new_segbuf = (segBuf_t*)malloc(sizeof(segBuf_t)); new_segbuf -> sentTime = -1; new_segbuf -> next = NULL; seg_t *new_seg = &(new_segbuf -> seg); build_segment_head(new_seg, tcb -> client_portNum, tcb -> server_portNum, real_length, DATA); new_seg -> header.seq_num = tcb -> next_seqNum; memcpy(new_seg -> data, data, real_length); tcb -> next_seqNum += real_length; /*add to send buf list*/ pthread_mutex_lock(tcb -> bufMutex); if(tcb -> sendBufHead == NULL){ assert(tcb -> sendBufunSent == NULL && tcb -> sendBufTail == NULL); tcb -> sendBufHead = new_segbuf; tcb -> sendBufunSent = new_segbuf; tcb -> sendBufTail = new_segbuf; /*start timer*/ pthread_t tid; pthread_create(&tid, NULL, sendBuf_timer, tcb); } else{ assert(tcb -> sendBufTail != NULL); tcb -> sendBufTail -> next = new_segbuf; tcb -> sendBufTail = new_segbuf; tcb -> sendBufunSent = (tcb -> sendBufunSent == NULL) ? new_segbuf : tcb -> sendBufunSent; } /*send the first unsent segment*/ if(tcb -> unAck_segNum < GBN_WINDOW){ //the first of the unsent seg must be the new seg assert(&(tcb -> sendBufunSent -> seg) == new_seg); sip_sendseg(sip_conn, tcb -> server_nodeID, new_seg); printf("send a data segment, seq %d\n", new_seg -> header.seq_num); new_segbuf -> sentTime = get_time(); tcb -> unAck_segNum ++; tcb -> sendBufunSent = tcb -> sendBufunSent -> next; } pthread_mutex_unlock(tcb -> bufMutex); if(real_length == length) return 1; //1 on success, -1 on fail else return stcp_client_send(sockfd, (char *)data + MAX_SEG_LEN, length - MAX_SEG_LEN); }
int main(int argc, char **argv) { //用于丢包率的随机数种子 srand(time(NULL)); //连接到SIP进程并获得TCP套接字描述符 int sip_conn = connectToSIP(); if(sip_conn<0) { printf("fail to connect to the local SIP process\n"); exit(1); } //初始化stcp客户端 stcp_client_init(sip_conn); sleep(STARTDELAY); char hostname[50]; printf("Enter server name to connect:"); scanf("%s",hostname); int server_nodeID = topology_getNodeIDfromname(hostname); if(server_nodeID == -1) { printf("host name error!\n"); exit(1); } else { printf("connecting to node %d\n",server_nodeID); } int number; printf("Enter client number to connect:"); scanf("%d",&number); if(number ==1 ){ sockfd = stcp_client_sock(CLIENTPORT1); if(sockfd<0) { printf("fail to create stcp client sock"); exit(1); } if(stcp_client_connect(sockfd,server_nodeID,SERVERPORT1)<0) { printf("fail to connect to stcp server\n"); exit(1); } printf("client connected to server, client port:%d, server port %d\n",CLIENTPORT1,SERVERPORT1); } else if(number ==2 ){ sockfd = stcp_client_sock(CLIENTPORT2); if(sockfd<0) { printf("fail to create stcp client sock"); exit(1); } if(stcp_client_connect(sockfd,server_nodeID,SERVERPORT2)<0) { printf("fail to connect to stcp server\n"); exit(1); } printf("client connected to server, client port:%d, server port %d\n",CLIENTPORT2,SERVERPORT2); } else if(number ==3 ){ sockfd = stcp_client_sock(CLIENTPORT3); if(sockfd<0) { printf("fail to create stcp client sock"); exit(1); } if(stcp_client_connect(sockfd,server_nodeID,SERVERPORT3)<0) { printf("fail to connect to stcp server\n"); exit(1); } printf("client connected to server, client port:%d, server port %d\n",CLIENTPORT3,SERVERPORT3); } else { printf("client number error!\n"); exit(1); } pthread_t msgthd,mainthd; pthread_attr_t attr; pthread_mutex_init(&wait_mutex,NULL); pthread_cond_init(&wait_cond,NULL); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE); memset(&send_msg,0,YY_MSG_HEADER_LENGTH+1024); memset(&rec_msg,0,YY_MSG_HEADER_LENGTH+1024); send_msg.protocol_name[0]='Y'; send_msg.protocol_name[1]='Y'; send_msg.protocol_name[2]='M'; send_msg.protocol_name[3]='G'; bool login=false; system("clear"); printf("Welcome to NJUCS Instant Messenger Demo Program!\nPlease input Your user name to login(The name's length shouled be less than 20 letters;The name only contains letters and digits!)\n(c)cls,(#)exit\n"); send_msg.service = 0X01; while(!login) { //main menu char a; scanf("%c",&a); gets(buffer); if(strcmp(buffer,"#")==0) break; else if(strcmp(buffer,"c")==0) { system("clear"); printf("Welcome to NJUCS Instant Messenger Demo Program!\nPlease input Your user name to login(The name's length shouled be less than 20 letters;The name only contains letters and digits!)\n(c)cls,(#)exit\n"); continue; } else if(strlen(buffer)>20) { printf("The inputed name is too long!input again:\n"); continue; } else { bool illegal=false; int i=0; for(i;i<strlen(buffer);i++) { if(!(('a'<=buffer[i]&& 'z'>=buffer[i]) ||('A'<=buffer[i] && 'Z' >=buffer[i])||('0'<=buffer[i] && '9'>=buffer[i])) ) { printf("The input is illegal!input again:\n"); illegal=true; break; } } if(illegal) continue; } strcpy(send_msg.send_usr,buffer); /*send the message to log in!*/ int len = YY_MSG_HEADER_LENGTH; stcp_client_send(sockfd,&len,sizeof(int)); stcp_client_send(sockfd,&send_msg,len); stcp_client_recv(sockfd,&len,sizeof(int)); stcp_client_recv(sockfd,&rec_msg,len); switch(rec_msg.service) { case 0x11:/*the user is aleady exist*/ printf("Sorry, The user %s already exists!input another:\n",rec_msg.send_usr);break; case 0x12:/*log in success!*/ strncpy(usrname,buffer,20); if(pthread_create(&mainthd, &attr, handle_main, NULL )!= 0) { perror("Thread creation problem"); exit(-1); } if(pthread_create(&msgthd, &attr, handle_msg, NULL)!= 0) { perror("Thread creation problem"); exit(-1); } pthread_join(mainthd,NULL); pthread_join(msgthd,NULL); login=true; break; default: printf("message error!error code:0x%02x",rec_msg.service);break; } } pthread_attr_destroy(&attr); pthread_mutex_destroy(&wait_mutex); pthread_cond_destroy(&wait_cond); pthread_exit(NULL); disconnectToSIP(sip_conn); }
/*thread function which's job is to carry out the order from the user*/ void *handle_main() { system("clear"); printf("Welcome to The Chatting program!User name:%s\n1.query the online users\n2.send message to someone\n3.send message to everyone\n4.View messages\n5.add someone to blacklist\n6.remove someone from blacklist\n7.View blacklist!\n(c)cls,(#)exit\n===================================================\n",usrname); while(true) { gets(buffer); if(strlen(buffer)!=1) { printf("input error!\n"); } else if(buffer[0]=='1'){ /*query the online users*/ send_msg.service = 0X02; int len=YY_MSG_HEADER_LENGTH; stcp_client_send(sockfd,&len,sizeof(int)); stcp_client_send(sockfd,&send_msg,len); pthread_mutex_lock(&wait_mutex); while(wait!=0x13) pthread_cond_wait(&wait_cond,&wait_mutex); wait=0x00; pthread_mutex_unlock(&wait_mutex); unsigned char online_users = (unsigned char)rec_msg.msg_content[0]; char *users=rec_msg.msg_content+1; int i; printf("Online users:\n"); for(i=0;i<online_users;i++) printf("User name: %s\n",users+i*20); } else if(buffer[0]=='2') { /*send messages to someone!*/ bool success=false; send_msg.service = 0x03; printf("Please enter the receive user's name:"); while(!success) { gets(buffer); if(strlen(buffer)>20) { printf("The user name inputed is too long!input again:\n"); continue; } else { bool illegal=false; int i=0; for(i;i<strlen(buffer);i++) { if(!(('a'<=buffer[i]&& 'z'>=buffer[i]) ||('A'<=buffer[i] && 'Z' >=buffer[i])||('0'<=buffer[i] && '9'>=buffer[i])) ) { printf("The input is illegal!input again:\n"); illegal=true; break; } } if(illegal) continue; } strcpy(send_msg.rec_usr,buffer); /*query whether the user is online*/ int len=YY_MSG_HEADER_LENGTH; stcp_client_send(sockfd,&len,sizeof(int)); stcp_client_send(sockfd,&send_msg,len); pthread_mutex_lock(&wait_mutex); while(wait!=0x14 && wait!=0x15) pthread_cond_wait(&wait_cond,&wait_mutex); wait=0x00; pthread_mutex_unlock(&wait_mutex); if(rec_msg.service == 0x15){ success=true; break; } else{ printf("The user is not exist or not online!\n"); break; } } if(success){ printf("Iuput the message content:\n"); gets(send_msg.msg_content); send_msg.service = 0x04; int len=YY_MSG_HEADER_LENGTH+strlen(send_msg.msg_content); stcp_client_send(sockfd,&len,sizeof(int)); stcp_client_send(sockfd,&send_msg,len); printf("The message has been sent out!\n"); } } else if(buffer[0]=='3') { /*send messages to everyone!*/ send_msg.service = 0x05; printf("Iuput the message content:\n"); gets(send_msg.msg_content); strcpy(send_msg.rec_usr,"everyone"); int len = YY_MSG_HEADER_LENGTH+strlen(send_msg.msg_content); stcp_client_send(sockfd,&len,sizeof(int)); stcp_client_send(sockfd,&send_msg,len); printf("The message has been sent out!\n"); } else if(buffer[0]=='4') { /*View the history messages!*/ if(msg_num==0) printf("No history messages!\n"); else { printf("The history messages :\n"); int i; for(i=0;i<msg_num;i++) { struct YY_MSG *msg=&history_msgs[(i+first_msg)%MAX_MSG_NUM]; printf("%s(to %s):%s\n",msg->send_usr,msg->rec_usr,msg->msg_content); } } } else if(buffer[0]=='5') { /*add someone to blacklist*/ bool success=false; send_msg.service = 0x03; printf("Please input the user's name:"); while(!success) { gets(buffer); if(strlen(buffer)>20) { printf("The user name inputed is too long!input again:\n"); continue; } else { bool illegal=false; int i=0; for(i;i<strlen(buffer);i++) { if(!(('a'<=buffer[i]&& 'z'>=buffer[i]) ||('A'<=buffer[i] && 'Z' >=buffer[i])||('0'<=buffer[i] && '9'>=buffer[i])) ) { printf("The input is illegal!input again:\n"); illegal=true; continue; } } if(illegal) continue; } strcpy(send_msg.rec_usr,buffer); int len = YY_MSG_HEADER_LENGTH; stcp_client_send(sockfd,&len,sizeof(int)); stcp_client_send(sockfd,&send_msg,len); pthread_mutex_lock(&wait_mutex); while(wait!=0x14 && wait!=0x15) pthread_cond_wait(&wait_cond,&wait_mutex); wait=0x00; pthread_mutex_unlock(&wait_mutex); if(rec_msg.service == 0x15){ success=true; break; } else{ printf("The user is not exist or not online!\n"); break; } } add_to_blacklist(); } else if(buffer[0]=='6'){ /*remove someone from blacklist*/ printf("Please input the user's name:"); gets(buffer); delete_from_blacklist(); } else if(buffer[0]=='7') { /*View blacklist*/ if(blacklistnum==0) printf("NO ONE!\n"); else { printf("blacklist:\n"); int i=0; for(i;i<blacklistnum;i++) printf("%s",blacklist[i]); } } else if(buffer[0]=='#'){ exit(0); } else if(buffer[0]=='c'){ system("clear"); printf("Welcome to The Chatting program!User name:%s\n1.query the online users\n2.send message to someone\n3.send message to everyone\n4.View messages\n5.add someone to blacklist\n6.remove someone from blacklist\n7.View blacklist!\n(c)cls,(#)exit\n===================================================\n",usrname); } else printf("input error!\n"); } pthread_exit(NULL); }
int main() { //用于丢包率的随机数种子 srand(time(NULL)); //启动重叠网络层并获取重叠网络层TCP套接字描述符 int son_conn = son_start(); if(son_conn<0) { printf("fail to start overlay network\n"); exit(1); } //初始化stcp客户端 stcp_client_init(son_conn); //在端口87上创建STCP客户端套接字, 并连接到STCP服务器端口88 int sockfd = stcp_client_sock(CLIENTPORT1); if(sockfd<0) { printf("fail to create stcp client sock"); exit(1); } if(stcp_client_connect(sockfd,SERVERPORT1)<0) { printf("fail to connect to stcp server\n"); exit(1); } printf("client connected to server, client port:%d, server port %d\n",CLIENTPORT1,SERVERPORT1); //在端口89上创建STCP客户端套接字, 并连接到STCP服务器端口90 int sockfd2 = stcp_client_sock(CLIENTPORT2); if(sockfd2<0) { printf("fail to create stcp client sock"); exit(1); } if(stcp_client_connect(sockfd2,SERVERPORT2)<0) { printf("fail to connect to stcp server\n"); exit(1); } printf("client connected to server, client port:%d, server port %d\n",CLIENTPORT2, SERVERPORT2); //通过第一个连接发送字符串 char mydata[6] = "hello"; int i; for(i=0;i<5;i++){ stcp_client_send(sockfd, mydata, 6); printf("send string:%s to connection 1\n",mydata); } //通过第二个连接发送字符串 char mydata2[7] = "byebye"; for(i=0;i<5;i++){ stcp_client_send(sockfd2, mydata2, 7); printf("send string:%s to connection 2\n",mydata2); } //等待一段时间, 然后关闭连接 sleep(WAITTIME); if(stcp_client_disconnect(sockfd)<0) { printf("fail to disconnect from stcp server\n"); exit(1); } if(stcp_client_close(sockfd)<0) { printf("fail to close stcp client\n"); exit(1); } if(stcp_client_disconnect(sockfd2)<0) { printf("fail to disconnect from stcp server\n"); exit(1); } if(stcp_client_close(sockfd2)<0) { printf("fail to close stcp client\n"); exit(1); } //停止重叠网络层 son_stop(son_conn); }