📄 echoclient.c
字号:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#include <fcntl.h>
#include <error.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "udpr.h"
#define MAXLINE 4096
#define SA ( struct sockaddr )
#define RTT_RTOCALC(ptr) ((ptr)->rtt_srtt + (4.0 * (ptr)->rtt_rttvar))
static struct rtt_info rttinfo;
static int rttinit = 0;
static struct msghdr msgsend, msgrecv;
static struct hdr {
unsigned int seq;
unsigned int ts;
} sendhdr, recvhdr;
static void sig_alarm(int signo);
static sigjmp_buf jmpbuf;
int main ( int argc , char ** argv )
{
int confd;
int ret_val;
int n;
socklen_t clilen;
socklen_t servlen;
struct sockaddr_in servaddr;
struct sockaddr_in cliaddr;
char sendbuf [ MAXLINE + 1 ];
char recvbuf [ MAXLINE + 1 ];
if ( argc != 3 ) {
printf ( "error : para : [Server Address] [Server Port]\n" );
exit ( 0 );
}
confd = socket ( AF_INET , SOCK_DGRAM , 0 );
if ( confd == -1 ){
printf ( "error : socket error \n" );
exit ( 1 );
}
bzero ( &servaddr , sizeof ( servaddr ) );
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons ( atoi ( argv[2] ) );
ret_val =inet_pton ( AF_INET , argv[1] , &servaddr.sin_addr );
if ( ret_val == -1 ) {
printf ( "error : inet_pton error !\n" );
exit ( 1 );
}
while ( fgets ( sendbuf , MAXLINE , stdin ) != NULL ) {
n = udp_send_recv( confd , sendbuf , strlen ( sendbuf ) ,\
recvbuf , MAXLINE , ( struct sockaddr * ) &servaddr , sizeof ( servaddr ) );
if ( n >0 ) {
recvbuf [ n ] = '\0' ;
printf ( "message : %s\n" , recvbuf );
}
}
exit ( 0 );
}
int udp_send_recv ( int sockfd , const void * send , int sendlen ,\
void * recv , int recvlen ,const struct sockaddr * servaddr , int servlen )
{
int n;
struct iovec iovsend[2];
struct iovec iovrecv[2];
if ( rttinit == 0 ){
rtt_init ( &rttinfo );
rttinit = 1;
}
sendhdr.seq ++ ;
msgsend.msg_name = ( void * )servaddr;
msgsend.msg_namelen = servlen;
msgsend.msg_iov = iovsend;
msgsend.msg_iovlen = 2;
iovsend[0].iov_base = &sendhdr;
iovsend[0].iov_len = sizeof ( struct hdr );
iovsend[1].iov_base = ( void * ) send ;
iovsend[1].iov_len = sendlen;
msgrecv.msg_name = NULL;
msgrecv.msg_namelen = 0;
msgrecv.msg_iov = iovrecv;
msgrecv.msg_iovlen = 2;
iovrecv[0].iov_base = &recvhdr;
iovrecv[0].iov_len = sizeof ( struct hdr ) ;
iovrecv[1].iov_base = ( void * ) recv ;
iovrecv[1].iov_len = recvlen ;
signal ( SIGALRM , sig_alarm );
rtt_newpack ( & rttinfo );
sendagain:
sendhdr.ts = rtt_ts ( &rttinfo );
n = sendmsg ( sockfd , &msgsend , 0 );
if ( n < 0 ){
perror ( "sendmsg failed\n" );
exit ( 1 );
}
printf ( "send %d bytes to server \n" , n );
printf ( "message : %s" , send );
printf ( "seq : %d.\n" , sendhdr.seq );
printf ( "ts : %d.\n" , sendhdr.ts );
printf ( "rtt_rto : %d.\n" , rttinfo.rtt_rto );
alarm ( rtt_start ( &rttinfo ) );
if ( sigsetjmp ( jmpbuf , 1 ) != 0 ) {
if ( rtt_timeout ( &rttinfo ) < 0 ) {
printf ( "udp_send_recv : no response , giving up !\n" );
rttinit = 0 ;
return -1 ;
}
goto sendagain;
}
do {
n = recvmsg ( sockfd , &msgrecv , 0 );
if ( n < 0 ) {
printf ( "error : recvmsg\n" );
exit ( 1 );
}
}while ( n < sizeof ( struct hdr ) || recvhdr.seq != sendhdr.seq );
alarm ( 0 );
rtt_stop ( & rttinfo ,rtt_ts ( &rttinfo ) - recvhdr.ts ) ;
printf ( "receive %d bytes from server\n" , n );
return ( n - sizeof ( struct hdr ) );
}
static void sig_alarm( int signo )
{
siglongjmp ( jmpbuf , 1 );
}
static float rtt_minmax(float rto)
{
if (rto < RTT_RXTMIN)
rto = RTT_RXTMIN;
else if (rto > RTT_RXTMAX)
rto = RTT_RXTMAX;
return (rto);
}
void rtt_init(struct rtt_info *ptr)
{
struct timeval tv;
gettimeofday(&tv, NULL);
ptr->rtt_base = tv.tv_sec;
ptr->rtt_rtt = 0;
ptr->rtt_srtt = 0;
ptr->rtt_rttvar = 0.75;
ptr->rtt_rto = rtt_minmax(RTT_RTOCALC(ptr));
}
unsigned int rtt_ts(struct rtt_info *ptr)
{
unsigned int ts;
struct timeval tv;
gettimeofday(&tv, NULL);
ts = ((tv.tv_sec - ptr->rtt_base) * 1000) + (tv. tv_usec / 1000);
return (ts);
}
void rtt_newpack(struct rtt_info *ptr)
{
ptr->rtt_nrexmt = 0;
}
int rtt_start(struct rtt_info *ptr)
{
return ((int) (ptr->rtt_rto + 0.5));
}
void rtt_stop(struct rtt_info *ptr, uint32_t ms)
{
double delta;
ptr->rtt_rtt = ms / 1000.0;
delta = ptr->rtt_rtt - ptr->rtt_srtt;
ptr->rtt_srtt += delta / 8;
if (delta < 0.0) delta = -delta;
ptr->rtt_rttvar += (delta - ptr->rtt_rttvar) / 4;
ptr->rtt_rto = rtt_minmax(RTT_RTOCALC(ptr));
}
int rtt_timeout(struct rtt_info *ptr)
{
ptr->rtt_rto *= 2;
if (++ptr->rtt_nrexmt > RTT_MAXNREXMT) return (-1);
return (0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -