static PRInt32 _udt_write(PRFileDesc *fd, const void *buf, PRInt32 amount) { UDTSOCKET s = get_socket_from_fd(fd); int rc = udt_send(s, (const char*)buf, amount, 0); if (rc < 0) { PRUdtSocketDesc* desc = (PRUdtSocketDesc*)(fd->secret); PR_Close(desc->sock_pair0); PR_Close(desc->sock_pair1); } return rc; }
static PRInt32 _udt_send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PRUdtSocketDesc* desc = (PRUdtSocketDesc*)(fd->secret); UDTSOCKET s = get_socket_from_fd(fd); int ret = udt_send(s, (char*)buf, amount, flags); if (ret < 0) { int udterrcode = udt_getErrorCode(); if ((UDT_ERRECONNLOST == udterrcode) || (UDT_ERRENOCONN == udterrcode)) { PR_Close(desc->sock_pair1); //ret = 0; } } return ret; }
static PRInt32 _udt_write(PRFileDesc *fd, const void *buf, PRInt32 amount) { ///fprintf(stdout, "%s:%d\n", __func__, __LINE__); UDTSOCKET s = get_socket_from_fd(fd); int rc = udt_send(s, (const char*)buf, amount, 0); if (rc < 0) { int udterrcode = udt_getlasterror_code(); if (UDT_EASYNCSND == udterrcode) { PR_SetError(PR_WOULD_BLOCK_ERROR, 0); } else { PR_SetError(PR_IO_ERROR, 0); } return -1; } return rc; }
/* Sends an ACK signal back to the sender. */ void receiver_acknowledge(int seqn) { int ret; ACKPacket ack = {"ACK", 0}; ack.seqn = seqn; ret = udt_send(&ack, sizeof(ACKPacket)); if (ret != NET_SUCCESS) { switch (ret) { case NET_TOOBIG: fprintf(stderr, "sender: NET_TOOBIG\n"); exit(1); case NET_SYSERR: fprintf(stderr, "sender: NET_SYSERR\n"); exit(1); default: fprintf(stderr, "sender: unknown\n"); exit(1); } } }
/* Sends a single packet via udt_send */ void send_packet(Packet* packet) { int ret; int packet_size = HEADERSIZE + packet->nbuffer; assert(packet_size > HEADERSIZE); if ((ret = udt_send(packet, packet_size)) != NET_SUCCESS) { switch (ret) { case NET_TOOBIG: fprintf(stderr, "sender: NET_TOOBIG\n"); exit(1); case NET_SYSERR: fprintf(stderr, "sender: NET_SYSERR\n"); exit(1); default: fprintf(stderr, "sender: unknown\n"); exit(1); } } }
static PRInt32 _udt_send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { ///fprintf(stdout, "%s:%d\n", __func__, __LINE__); UDTSOCKET s = get_socket_from_fd(fd); int rc = udt_send(s, (char*)buf, amount, flags); // peek is not supported in udt if (PR_MSG_PEEK & flags) { PR_SetError(PR_WOULD_BLOCK_ERROR, 0); return -1; } if (rc < 0) { int udterrcode = udt_getlasterror_code(); if (UDT_EASYNCSND == udterrcode) { PR_SetError(PR_WOULD_BLOCK_ERROR, 0); } else { PR_SetError(PR_IO_ERROR, 0); } return -1; } return rc; }
int main(int argc, char* argv[]) { if ((3 != argc) || (0 == atoi(argv[2]))) { printf("usage: client server_ip server_port\n"); return -1; } if (udt_startup() != 0) { printf("udt : startup failed:%s\n", udt_getlasterror_desc()); return -1; } struct addrinfo hints, *local, *peer; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; //hints.ai_socktype = SOCK_DGRAM; if (0 != getaddrinfo(NULL, argv[2], &hints, &local)) { printf("incorrect network address.\n"); return -1; } UDTSOCKET client = udt_socket(local->ai_family, local->ai_socktype, local->ai_protocol); // UDT Options //UDT::setsockopt(client, 0, UDT_CC, new CCCFactory<CUDPBlast>, sizeof(CCCFactory<CUDPBlast>)); //UDT::setsockopt(client, 0, UDT_MSS, new int(9000), sizeof(int)); //UDT::setsockopt(client, 0, UDT_SNDBUF, new int(10000000), sizeof(int)); //UDT::setsockopt(client, 0, UDP_SNDBUF, new int(10000000), sizeof(int)); //UDT::setsockopt(client, 0, UDT_MAXBW, new int64_t(12500000), sizeof(int)); // for rendezvous connection, enable the code below /* UDT::setsockopt(client, 0, UDT_RENDEZVOUS, new bool(true), sizeof(bool)); if (UDT::ERROR == UDT::bind(client, local->ai_addr, local->ai_addrlen)) { cout << "bind: " << UDT::getlasterror().getErrorMessage() << endl; return 0; } */ freeaddrinfo(local); if (0 != getaddrinfo(argv[1], argv[2], &hints, &peer)) { printf("incorrect server/peer address. %s:%s\n", argv[1], argv[2]); return -1; } // connect to the server, implict bind if (UDT_ERROR == udt_connect(client, peer->ai_addr, peer->ai_addrlen)) { printf("connect: %s\n", udt_getlasterror_desc()); return 0; } freeaddrinfo(peer); // using CC method //CUDPBlast* cchandle = NULL; //int temp; //UDT::getsockopt(client, 0, UDT_CC, &cchandle, &temp); //if (NULL != cchandle) // cchandle->setRate(500); char* data = malloc(sizeof(char) * DATA_LEN); memset(data, 'a', DATA_LEN); struct timeval t1, t2; gettimeofday(&t1, NULL); for (int i = 0; i < N_SEND; i ++) { //printf("i = %d\n", i); if (UDT_ERROR == udt_send(client, data, DATA_LEN, 0)) { printf("send:%s\n", udt_getlasterror_desc()); break; } } gettimeofday(&t2, NULL); int elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0; // sec to ms elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0; // us to ms printf("finished to write data in %d milliseconds\n", elapsedTime); udt_close(client); free(data); if (udt_cleanup() != 0) { printf("cleanup:%s", udt_getlasterror_desc()); } return 0; }
int main(int argc, char **argv ) { char ch; char buf[80]; char sendline[MAXLINE]; char recvline[MAXLINE]; int udt; while ((ch = getopt(argc,argv,"p:R:P:h")) != -1) { switch(ch) { case 'p': local_port = atol(optarg); break; case 'R': remote_addr = ntohl(inet_addr(optarg)); //!!! needs nhotl as udt requires host order! break; case 'P': remote_port = atol(optarg); break; case 'h': fprintf(stdout, PROGRAM_INFO); fprintf(stdout, "usage: udtdemo -p port -P port [-R address]\n\n"); fprintf(stdout, " p port : local UDP socket binds to `port'\n" ); fprintf(stdout, " P port : UDP datagrams will be sent to the remote `port'\n" ); fprintf(stdout, " R address : UDP datagrams will be sent to the remote host \n as specified by `address' (an implicit is 127.0.0.1)\n\n" ); exit(EXIT_SUCCESS); } } fprintf(stderr, PROGRAM_INFO); // Complain if something is missing or wrong. if (remote_addr == 0 || remote_port == 0 || local_port == 0) { fprintf(stderr, "Missing required arguments! Type '%s -h' for help.\n", PROGRAM); exit(EXIT_FAILURE); } fprintf(stderr, "Data channel from localhost:%d to %s:%d.\n", local_port, inet_ntop(AF_INET, &remote_addr, buf, 80), remote_port); fprintf(stderr, "Write data content, press ENTER to send the packet.\n"); // It is important to init UDT! udt = udt_init(local_port); fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // make stdin reading non-clocking fd_set readfds; FD_ZERO(&readfds); FD_SET(udt, &readfds); FD_SET(STDIN_FILENO, &readfds); while (select(udt+1, &readfds, NULL, NULL, NULL)) { if (FD_ISSET(STDIN_FILENO, &readfds) && fgets(sendline, MAXLINE, stdin)>0) { // we have read a new line to send if (!udt_send(udt, remote_addr, remote_port, sendline, strlen(sendline))) { perror("udtdemo: "); // some error } } if (FD_ISSET(udt, &readfds)) { // We have a new message to print int n = udt_recv(udt, recvline, MAXLINE, NULL, NULL); recvline[n] = 0; fputs(recvline, stdout); } // and again! FD_ZERO(&readfds); FD_SET(udt, &readfds); FD_SET(STDIN_FILENO, &readfds); } return EXIT_SUCCESS; }
bool process(params_t* args) { ipk_sock_t udt = IPK_SOCK_INVALID; rdt_t* rdt = NULL; #ifndef _WIN32 if (!ipk_fd_block_mode(STDIN_FILENO, false)) { return false; } #endif udt = udt_init(args->src_port); if (!udt_connect(udt, args->dst_port)) { goto return_false; } rdt = rdt_new(); if (!rdt) { goto return_false; } if (!rdt_client_start(rdt)) { goto return_false; } bool eof = false; char buf[BUF_MAXLEN]; char rcvbuf[UDT_PACKET_MAXLEN]; char sndbuf[UDT_PACKET_MAXLEN]; size_t nbuf = 0; size_t nrcvbuf = 0; size_t nsndbuf = 0; struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 100000; #ifdef _WIN32 int nfds = 0; // ignored on win32 #else int nfds = max(STDIN_FILENO, udt) + 1; #endif fd_set rfds, wfds; while (!_terminate) { FD_ZERO(&rfds); FD_ZERO(&wfds); if (nsndbuf == 0) { nsndbuf = _countof(sndbuf); rdt_client_step(rdt, rcvbuf, nrcvbuf, sndbuf, &nsndbuf); } else { rdt_client_step(rdt, rcvbuf, nrcvbuf, NULL, NULL); } nrcvbuf = 0; FD_SET(udt, &rfds); if (nsndbuf > 0) { FD_SET(udt, &wfds); } #ifndef _WIN32 if (!eof && nbuf < _countof(buf)) { FD_SET(STDIN_FILENO, &rfds); } #endif if (nbuf > 0 && rdt_data_write(rdt, buf, nbuf)) { nbuf = 0; } else if (eof) { if (rdt_client_done(rdt)) break; } int numfd = select(nfds, &rfds, &wfds, NULL, &tv); if (numfd == -1) { ipk_sock_perror(ipk_sock_errno); } else if (numfd == 0) { continue; } else { #ifndef _WIN32 if (FD_ISSET(STDIN_FILENO, &rfds)) { #else if (!eof) { #endif size_t erecv = _countof(buf) - nbuf; size_t nrecv = fread(buf + nbuf, sizeof(char), erecv, stdin); _ipk_verbose_log("Readed %zu from stdin.", nrecv); nbuf += nrecv; if (nrecv != erecv) { if (feof(stdin)) { eof = true; } else if (ferror(stdin) && !ipk_sock_is_recoverable(errno)) { ipk_perror(errno); // send RST } } } if (FD_ISSET(udt, &wfds)) { int nsnd = udt_send(udt, sndbuf, nsndbuf); if (nsnd == -1) { ipk_sock_perror(ipk_sock_errno); goto return_false; } else if (nsnd > 0) { nsndbuf = 0; sndbuf[nsnd] = '\0'; _ipk_debug_log("#%x <<<\n%s", udt, sndbuf); _ipk_debug_log("#%x /<<<", udt); } else { // send again } } if (FD_ISSET(udt, &rfds)) { int nrcv = udt_recv(udt, rcvbuf, _countof(rcvbuf)); if (nrcv == -1) { ipk_sock_perror(ipk_sock_errno); goto return_false; } else if (nrcv > 0) { nrcvbuf = nrcv; rcvbuf[nrcv] = '\0'; _ipk_debug_log("#%x >>>\n%s", udt, rcvbuf); _ipk_debug_log("#%x />>>", udt); } else { // read again } } } } rdt_dispose(rdt); ipk_sock_close(udt); return true; return_false: rdt_dispose(rdt); ipk_sock_close(udt); return false; } int main(int argc, char* argv[]) { params_t params; memset(¶ms, '\0', sizeof(params_t)); setlocale(LC_ALL, ""); ipk_set_log_func(&mylog); ipk_set_log_level(1); if (!parseargs(argc, argv, ¶ms)) { _ipk_error_log("%s", "Chyba: nebyl zadan povinny parametr."); fprintf(stdout, "%s", "Synopsis: rdtclient -s source_port -d dest_port\n"); return EXIT_FAILURE; } ipk_set_log_level(params.verbose_lvl); if (params.action == ACT_HELP) { fprintf(stdout, "%s", "Spolehliva komunikace, projekt c. 3 pro predmet IPK.\n" "Autor: Radek Sevcik, [email protected]\n" "\n" "Synopsis: rdtclient -s source_port -d dest_port\n" "\n" "Parametry:\n" " -h\t\t\tVypise napovedu.\n" " -s source_port\tNasloucha na portu source_port.\n" " -d dest_port\t\tPripoji se na port dest_port.\n"); return EXIT_SUCCESS; } // sigint (ctrl+c), sigterm #ifdef _WIN32 if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)&on_console_handler, true)) { ipk_perror_win(GetLastError()); return EXIT_FAILURE; } #else if (SIG_ERR == signal(SIGINT, &on_signal)) { ipk_perror(errno); return EXIT_FAILURE; } if (SIG_ERR == signal(SIGTERM, &on_signal)) { ipk_perror(errno); return EXIT_FAILURE; } #endif if (!ipk_sock_init()) { return EXIT_FAILURE; } if (0 != atexit(&cleanup)) { _ipk_error_log("%s", "Chyba: nedostatek pameti"); return EXIT_FAILURE; } return process(¶ms) ? EXIT_SUCCESS : EXIT_FAILURE; }
// reciever int main( int argc, char **argv ) { int min=0,sec =0 ,msec =0; struct sockaddr_in serv_addr; struct sockaddr_in clnt_addr; int serv_sock; int clnt_addr_size; int result = 0; uint16_t check; int r_seq = 0, ack = 1, pre_seq=0; int correct_pkt =0, dup_pkt=0, rcv_pkt=0; int rcv_byte=0; struct timeval ti1,ti2; int read_byte; int rcv_start =0, rcv_end=0; DEBUG_ON = 1; // print debug message if(argc != 2){ printf("Usage : %s <port>\n", argv[0]); exit(1); } if ((serv_sock = socket( AF_INET, SOCK_DGRAM, 0 )) < 0) error(1, errno, "socket creation failed" ); memset(&serv_addr, 0 , sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(atoi(argv[1])); if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) error(1, errno, "socket bind failed"); while(1) { memset(&dataPacket,0,sizeof(dataPacket)); memset(&controlPacket,0,sizeof(controlPacket)); clnt_addr_size = sizeof(clnt_addr); read_byte = recvfrom(serv_sock, &dataPacket, sizeof(dataPacket), 0, (struct sockaddr *)&clnt_addr, &clnt_addr_size); debug("========================================================\n"); debug("[DATA] rcv Packet: type[%d] seq[%d] len[%d] checksum[%x]\n", dataPacket.header.type, r_seq, dataPacket.header.len, dataPacket.header.checksum); if(read_byte > 0){ if(rcv_start ==0){ gettimeofday(&ti1,NULL); rcv_start =1; } if(dataPacket.header.type == DATA){ // DATA 인경우 잘못된 전송 혹은 제대로된 전송 if(checkPacket(&dataPacket, r_seq)){ connect(serv_sock, (struct sockaddr *)&clnt_addr,clnt_addr_size); make_cpkt(&controlPacket, ACK, ack); write(1, dataPacket.data,dataPacket.header.len-HEADER_LEN); if(udt_send(serv_sock, &controlPacket, sizeof(controlPacket)) <0 ) error(1, errno, "ACK udt_send error\n"); debug("[ACK] send Packet: type[%d] seq[%d] len[%d] checksum[%x]\n", controlPacket.header.type, ack, controlPacket.header.len, controlPacket.header.checksum); correct_pkt++; rcv_pkt++; rcv_byte=rcv_byte + dataPacket.header.len - HEADER_LEN; pre_seq=r_seq; r_seq++; ack = r_seq+1; } else{ if(dataPacket.header.seq == pre_seq) // error 인 duplicate 도 포함시킨다 dup_pkt++; connect(serv_sock, (struct sockaddr *)&clnt_addr,clnt_addr_size); make_cpkt(&controlPacket, ACK, r_seq); if(udt_send(serv_sock, &controlPacket, sizeof(controlPacket)) <0 ) error(1, errno, "ACK udt_send error\n"); rcv_pkt++; debug("[ReACK] send Packet: type[%d] seq[%d] len[%d] checksum[%x]\n", controlPacket.header.type, r_seq, controlPacket.header.len, controlPacket.header.checksum); } } else if(dataPacket.header.type == END){ // END 인경우 잘못된 전송 혹은 제대로된 전송 if(checkCPacket(&dataPacket, r_seq)){ if(rcv_end == 0){ gettimeofday(&ti2,NULL); if((ti2.tv_sec - ti1.tv_sec)>0){ min = (ti2.tv_sec - ti1.tv_sec)/60; sec = (ti2.tv_sec - ti1.tv_sec)%60; } else if((ti1.tv_sec-ti2.tv_sec)>0){ min = (ti1.tv_sec - ti2.tv_sec)/60; sec = (ti1.tv_sec - ti2.tv_sec)%60; } if((ti2.tv_usec - ti1.tv_usec)>0) msec = (ti2.tv_usec - ti1.tv_usec)/1000; else if((ti1.tv_usec - ti2.tv_usec)>0) msec = (ti1.tv_usec - ti2.tv_usec)/1000; debug("===============================================================\n"); // debug("start %d usec\n", ti1.tv_usec); // debug("end% d usec\n", ti2.tv_usec); debug("===============================================================\n"); debug("%d of DATA packets received (including retransmitted packets)\n",rcv_pkt); debug("%d of duplicated DATA packets received\n",dup_pkt); debug("%d of DATA packets correctly received\n",correct_pkt); debug("%d of bytes correctly received\n",rcv_byte); debug("Time duration : %d min %d sec %d msec\n",min,sec,msec); debug("Troughput : %d (byte/second)\n",rcv_byte/(ti2.tv_sec - ti1.tv_sec)); debug("===============================================================\n"); rcv_end =1; } connect(serv_sock, (struct sockaddr *)&clnt_addr,clnt_addr_size); make_cpkt(&controlPacket, END, ack); if(udt_send(serv_sock, &controlPacket, sizeof(controlPacket)) <0 ) error(1, errno, "ACK udt_send error\n"); debug("[END] send Packet: type[%d] seq[%d] len[%d] checksum[%x]\n", controlPacket.header.type, ack, controlPacket.header.len, controlPacket.header.checksum); return 0; } else{ connect(serv_sock, (struct sockaddr *)&clnt_addr,clnt_addr_size); make_cpkt(&controlPacket, ACK, r_seq); if(udt_send(serv_sock, &controlPacket, sizeof(controlPacket)) <0 ) error(1, errno, "ACK udt_send error\n"); debug("[ReACK] send Packet: type[%d] seq[%d] len[%d] checksum[%x]\n", controlPacket.header.type, r_seq, controlPacket.header.len, controlPacket.header.checksum); } } } if(read_byte < 0) error(1, errno, "recvfrom failed"); } }