⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 echoclient.c

📁 chat program in linux use multiple broadcase implement by c language
💻 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 + -