client.c 9.3 KB
Newer Older
S
Shuaiqiang Chang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
S
Shuaiqiang Chang 已提交
15

S
Shuaiqiang Chang 已提交
16
#include <argp.h>
S
Shuaiqiang Chang 已提交
17 18 19 20 21 22 23 24 25 26 27 28 29
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
H
Hui Li 已提交
30
#include <wordexp.h>
S
Shuaiqiang Chang 已提交
31

H
Hui Li 已提交
32 33
#define    MAX_PKG_LEN          (64*1000)
#define    BUFFER_SIZE          (MAX_PKG_LEN + 1024)
H
Hui Li 已提交
34 35
#define    TEST_FQDN_LEN        128
#define    TEST_IPv4ADDR_LEN    16
S
Shuaiqiang Chang 已提交
36 37

typedef struct {
H
Hui Li 已提交
38 39
  uint16_t port;
  uint32_t hostIp;
H
Hui Li 已提交
40
  char     fqdn[TEST_FQDN_LEN];
H
Hui Li 已提交
41
  uint16_t pktLen;
H
Hui Li 已提交
42
} info_s;
S
Shuaiqiang Chang 已提交
43

S
Shuaiqiang Chang 已提交
44
typedef struct Arguments {
H
Hui Li 已提交
45 46
  char     host[TEST_IPv4ADDR_LEN];
  char     fqdn[TEST_FQDN_LEN];
S
Shuaiqiang Chang 已提交
47 48
  uint16_t port;
  uint16_t max_port;
H
Hui Li 已提交
49
  uint16_t pktLen;
S
Shuaiqiang Chang 已提交
50 51 52
} SArguments;

static struct argp_option options[] = {
H
Hui Li 已提交
53
    {0, 'h', "host ip", 0, "The host ip to connect to TDEngine. Default is localhost.", 0},
H
Hui Li 已提交
54
    {0, 'p', "port", 0, "The TCP or UDP port number to use for the connection. Default is 6030.", 1},
H
Hui Li 已提交
55 56
    {0, 'm', "max port", 0, "The max TCP or UDP port number to use for the connection. Default is 6042.", 2},
    {0, 'f', "host fqdn", 0, "The host fqdn to connect to TDEngine.", 3},
H
Hui Li 已提交
57
    {0, 'l', "test pkg len", 0, "The len of pkg for test. Default is 1000 Bytes, max not greater than 64k Bytes.\nNotes: This parameter must be consistent between the client and the server.", 3}};
S
Shuaiqiang Chang 已提交
58 59

static error_t parse_opt(int key, char *arg, struct argp_state *state) {
H
Hui Li 已提交
60
  wordexp_t full_path;
S
Shuaiqiang Chang 已提交
61 62 63
  SArguments *arguments = state->input;
  switch (key) {
    case 'h':
H
Hui Li 已提交
64 65 66 67 68 69
      if (wordexp(arg, &full_path, 0) != 0) {
        fprintf(stderr, "Invalid host ip %s\n", arg);
        return -1;
      }
      strcpy(arguments->host, full_path.we_wordv[0]);
      wordfree(&full_path);
S
Shuaiqiang Chang 已提交
70 71 72 73 74 75 76
      break;
    case 'p':
      arguments->port = atoi(arg);
      break;
    case 'm':
      arguments->max_port = atoi(arg);
      break;
H
Hui Li 已提交
77 78 79
    case 'l':
      arguments->pktLen = atoi(arg);
      break;
H
Hui Li 已提交
80 81 82 83 84 85 86 87
    case 'f':
      if (wordexp(arg, &full_path, 0) != 0) {
        fprintf(stderr, "Invalid host fqdn %s\n", arg);
        return -1;
      }
      strcpy(arguments->fqdn, full_path.we_wordv[0]);
      wordfree(&full_path);
      break;    
H
Hui Li 已提交
88

H
Hui Li 已提交
89
    default:
H
Hui Li 已提交
90
      return ARGP_ERR_UNKNOWN;
S
Shuaiqiang Chang 已提交
91 92 93 94 95 96
  }
  return 0;
}

static struct argp argp = {options, parse_opt, 0, 0};

H
Hui Li 已提交
97
int checkTcpPort(info_s *info) {
S
Shuaiqiang Chang 已提交
98 99 100 101 102
  int   clientSocket;

  struct sockaddr_in serverAddr;
  char               sendbuf[BUFFER_SIZE];
  char               recvbuf[BUFFER_SIZE];
H
Hongze Cheng 已提交
103
  int                iDataNum = 0;
S
Shuaiqiang Chang 已提交
104
  if ((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
H
Hui Li 已提交
105
    printf("socket() fail: %s\n", strerror(errno));
H
Hui Li 已提交
106
    return -1;
S
Shuaiqiang Chang 已提交
107
  }
H
Hui Li 已提交
108 109 110 111 112 113 114 115 116 117 118 119

  // set send and recv overtime
  struct timeval timeout;  
  timeout.tv_sec = 2;  //s
  timeout.tv_usec = 0; //us  
  if (setsockopt(clientSocket, SOL_SOCKET,SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval)) == -1) {
    perror("setsockopt send timer failed:");
  }
  if (setsockopt(clientSocket, SOL_SOCKET,SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval)) == -1) {
    perror("setsockopt recv timer failed:");
  }

S
Shuaiqiang Chang 已提交
120
  serverAddr.sin_family = AF_INET;
H
Hui Li 已提交
121
  serverAddr.sin_port = htons(info->port);
S
Shuaiqiang Chang 已提交
122

H
Hui Li 已提交
123
  serverAddr.sin_addr.s_addr = info->hostIp;
S
Shuaiqiang Chang 已提交
124

H
Hui Li 已提交
125
  //printf("=================================\n");
S
Shuaiqiang Chang 已提交
126
  if (connect(clientSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
H
Hui Li 已提交
127
    printf("connect() fail: %s\t", strerror(errno));
H
Hui Li 已提交
128
    return -1;
S
Shuaiqiang Chang 已提交
129
  }
H
Hui Li 已提交
130
  //printf("Connect to: %s:%d...success\n", host, port);
H
Hui Li 已提交
131 132 133
  memset(sendbuf, 0, BUFFER_SIZE);
  memset(recvbuf, 0, BUFFER_SIZE);

H
Hui Li 已提交
134 135 136
  struct in_addr ipStr;
  memcpy(&ipStr, &info->hostIp, 4);
  sprintf(sendbuf, "client send tcp pkg to %s:%d, content: 1122334455", inet_ntoa(ipStr), info->port);
H
Hui Li 已提交
137
  sprintf(sendbuf + info->pktLen - 16, "1122334455667788");
S
Shuaiqiang Chang 已提交
138

H
Hui Li 已提交
139
  send(clientSocket, sendbuf, info->pktLen, 0);
S
Shuaiqiang Chang 已提交
140

H
Hui Li 已提交
141 142 143 144 145 146 147 148 149 150 151 152 153
  memset(recvbuf, 0, BUFFER_SIZE);
  int   nleft, nread;
  char *ptr = recvbuf;
  nleft = info->pktLen;
  while (nleft > 0) {
    nread = recv(clientSocket, ptr, BUFFER_SIZE, 0);;
  
    if (nread == 0) {
      break;
    } else if (nread < 0) {
      if (errno == EINTR) {
        continue;
      } else {
H
Hui Li 已提交
154
        printf("recv ack pkg from TCP port: %d fail:%s.\n", info->port, strerror(errno));
H
Hui Li 已提交
155 156 157 158 159 160 161 162 163 164
        close(clientSocket);
        return -1;
      }
    } else {
      nleft -= nread;
      ptr += nread;
      iDataNum += nread;
    }      
  }

H
Hui Li 已提交
165
  if (iDataNum < info->pktLen) {
H
Hui Li 已提交
166
    printf("recv ack pkg len: %d, less than req pkg len: %d from tcp port: %d\n", iDataNum, info->pktLen, info->port);
H
Hui Li 已提交
167 168 169
    return -1;
  }
  //printf("Read ack pkg len:%d from tcp port: %d, buffer: %s  %s\n", info->pktLen, port, recvbuf, recvbuf+iDataNum-8);
S
Shuaiqiang Chang 已提交
170 171

  close(clientSocket);
H
Hui Li 已提交
172
  return 0;
S
Shuaiqiang Chang 已提交
173 174
}

H
Hui Li 已提交
175
int checkUdpPort(info_s *info) {
S
Shuaiqiang Chang 已提交
176 177 178 179 180
  int   clientSocket;

  struct sockaddr_in serverAddr;
  char               sendbuf[BUFFER_SIZE];
  char               recvbuf[BUFFER_SIZE];
H
Hongze Cheng 已提交
181
  int                iDataNum = 0;
S
Shuaiqiang Chang 已提交
182 183
  if ((clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
    perror("socket");
H
Hui Li 已提交
184
    return -1;
S
Shuaiqiang Chang 已提交
185
  }
H
Hui Li 已提交
186 187 188 189 190 191 192 193 194 195 196

  // set overtime 
  struct timeval timeout;
  timeout.tv_sec = 2;  //s
  timeout.tv_usec = 0; //us
  if (setsockopt(clientSocket, SOL_SOCKET,SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval)) == -1) {
    perror("setsockopt send timer failed:");
  }
  if (setsockopt(clientSocket, SOL_SOCKET,SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval)) == -1) {
    perror("setsockopt recv timer failed:");
  }
H
Hui Li 已提交
197
  
S
Shuaiqiang Chang 已提交
198
  serverAddr.sin_family = AF_INET;
H
Hui Li 已提交
199 200
  serverAddr.sin_port = htons(info->port);
  serverAddr.sin_addr.s_addr = info->hostIp;
H
Hui Li 已提交
201 202 203
  
  memset(sendbuf, 0, BUFFER_SIZE);
  memset(recvbuf, 0, BUFFER_SIZE);
S
Shuaiqiang Chang 已提交
204

H
Hui Li 已提交
205 206 207
  struct in_addr ipStr;
  memcpy(&ipStr, &info->hostIp, 4);
  sprintf(sendbuf, "client send udp pkg to %s:%d, content: 1122334455", inet_ntoa(ipStr), info->port);
H
Hui Li 已提交
208
  sprintf(sendbuf + info->pktLen - 16, "1122334455667788");
S
Shuaiqiang Chang 已提交
209

S
Shuaiqiang Chang 已提交
210
  socklen_t sin_size = sizeof(*(struct sockaddr *)&serverAddr);
S
Shuaiqiang Chang 已提交
211

H
Hui Li 已提交
212
  int code = sendto(clientSocket, sendbuf, info->pktLen, 0, (struct sockaddr *)&serverAddr, (int)sin_size);
H
Hui Li 已提交
213 214 215 216
  if (code < 0) {
    perror("sendto");
    return -1;
  }
S
Shuaiqiang Chang 已提交
217 218 219

  iDataNum = recvfrom(clientSocket, recvbuf, BUFFER_SIZE, 0, (struct sockaddr *)&serverAddr, &sin_size);

H
Hui Li 已提交
220
  if (iDataNum < info->pktLen) {
H
Hui Li 已提交
221
    printf("Read ack pkg len: %d, less than req pkg len: %d from udp port: %d\t\t", iDataNum, info->pktLen, info->port);
H
Hui Li 已提交
222 223 224 225
    return -1;
  }
  
  //printf("Read ack pkg len:%d from udp port: %d, buffer: %s  %s\n", info->pktLen, port, recvbuf, recvbuf+iDataNum-8);
S
Shuaiqiang Chang 已提交
226
  close(clientSocket);
H
Hui Li 已提交
227
  return 0;
S
Shuaiqiang Chang 已提交
228 229
}

H
Hui Li 已提交
230 231 232 233
int32_t getIpFromFqdn(const char *fqdn, uint32_t* ip) {
  struct addrinfo hints = {0};
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
S
Shuaiqiang Chang 已提交
234

H
Hui Li 已提交
235
  struct addrinfo *result = NULL;
S
Shuaiqiang Chang 已提交
236

H
Hui Li 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249
  int32_t ret = getaddrinfo(fqdn, NULL, &hints, &result);
  if (result) {
    struct sockaddr *sa = result->ai_addr;
    struct sockaddr_in *si = (struct sockaddr_in*)sa;
    struct in_addr ia = si->sin_addr;
    *ip = ia.s_addr;
    freeaddrinfo(result);
    return 0;
  } else {
    printf("Failed get the ip address from fqdn:%s, code:%d, reason:%s", fqdn, ret, gai_strerror(ret));
    return -1;
  }
}
S
Shuaiqiang Chang 已提交
250

H
Hui Li 已提交
251 252 253 254 255 256
void checkPort(uint32_t hostIp, uint16_t startPort, uint16_t maxPort, uint16_t pktLen) {
  int ret;
  info_s info;
  memset(&info, 0, sizeof(info_s));
  info.hostIp   = hostIp;
  info.pktLen   = pktLen;
S
Shuaiqiang Chang 已提交
257

H
Hui Li 已提交
258
  for (uint16_t port = startPort; port <= maxPort; port++) {
H
Hui Li 已提交
259 260
    //printf("test: %s:%d\n", info.host, port);
    printf("\n");
H
Hui Li 已提交
261 262 263 264

    info.port = port;
    ret = checkTcpPort(&info);
    if (ret != 0) {
H
Hui Li 已提交
265
      printf("tcp port:%d test fail.\t\n", port);
H
Hui Li 已提交
266
    } else {
H
Hui Li 已提交
267
      printf("tcp port:%d test ok.\t\t", port);
H
Hui Li 已提交
268 269
    }
    
H
Hui Li 已提交
270
    ret = checkUdpPort(&info);
H
Hui Li 已提交
271
    if (ret != 0) {
H
Hui Li 已提交
272
      printf("udp port:%d test fail.\t\n", port);
H
Hui Li 已提交
273
    } else {
H
Hui Li 已提交
274
      printf("udp port:%d test ok.\t\t", port);
H
Hui Li 已提交
275
    }
S
Shuaiqiang Chang 已提交
276
  }
H
Hui Li 已提交
277
  
H
Hui Li 已提交
278
  printf("\n");
H
Hui Li 已提交
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
  return ;
}

int main(int argc, char *argv[]) {
  SArguments arguments = {"127.0.0.1", "", 6030, 6042, 1000};
  int        ret;
  
  argp_parse(&argp, argc, argv, 0, 0, &arguments);
  if (arguments.pktLen > MAX_PKG_LEN) {
    printf("test pkg len overflow: %d, max len not greater than %d bytes\n", arguments.pktLen, MAX_PKG_LEN);
    exit(0);
  }

  printf("host ip: %s\thost fqdn: %s\tport: %d\tmax_port: %d\tpkgLen: %d\n", arguments.host, arguments.fqdn, arguments.port, arguments.max_port, arguments.pktLen);

  if (arguments.host[0] != 0) {
    printf("\nstart connect to %s test:\n", arguments.host);
    checkPort(inet_addr(arguments.host), arguments.port, arguments.max_port, arguments.pktLen);
    printf("\n");
  }

  if (arguments.fqdn[0] != 0) {
    uint32_t hostIp = 0;
    ret = getIpFromFqdn(arguments.fqdn, &hostIp);
    if (ret) {
      printf("\n");
      return 0;    
    }
    printf("\nstart connetc to %s test:\n", arguments.fqdn);
    checkPort(hostIp, arguments.port, arguments.max_port, arguments.pktLen);
    printf("\n");
  }

H
Hui Li 已提交
312
  return 0;
H
Hui Li 已提交
313
}