spartserv

Simple client and server for the spartan protocol
git clone https://noulin.net/git/spartserv.git
Log | Files | Refs | README

spartclientudp.c (2518B)


      1 // Usage: spartclient hostname port path
      2 #include <stdio.h>
      3 #include <sys/types.h>
      4 #include <sys/socket.h>
      5 #include <netdb.h>
      6 #include <netinet/in.h>
      7 #include <string.h>
      8 #include <stdlib.h>
      9 #include <ctype.h>
     10 #include <unistd.h>
     11 
     12 int64_t parseInt(const char *string) {
     13     while (!isdigit(*string) && *string != '-' && *string != 0) {
     14         string++;
     15     }
     16     int64_t r = strtoll(string, NULL, 10);
     17     return(r);
     18 }
     19 
     20 int main(int ac, char **av){
     21     int sock;
     22     struct sockaddr_in server;
     23     struct hostent *hp;
     24     int mysock;
     25     char buf[65536] = {0};
     26     int rval;
     27     int i;
     28 
     29     if (ac < 4) {
     30         puts("Usage: spartclient hostname port path");
     31         return 0;
     32     }
     33 
     34     sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
     35     if (sock < 0){
     36         perror("Failed to create socket");
     37     }
     38 
     39     server.sin_family = AF_INET;
     40 
     41     hp = gethostbyname(av[1]);
     42     if (hp==0) {
     43         perror("gethostbyname failed");
     44         close(sock);
     45         exit(1);
     46     }
     47 
     48     memcpy(&server.sin_addr, hp->h_addr, hp->h_length);
     49 
     50     int64_t port = parseInt(av[2]);
     51 
     52     if (port < 1 || port > 65000) {
     53         printf("Invalid port %d.\n", port);
     54         return 1;
     55     }
     56 
     57     server.sin_port = htons(port);
     58 
     59     // open socket for response
     60     struct sockaddr_in respaddr;
     61     int rsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
     62     if (rsock < 0){
     63         perror("Failed to create socket");
     64     }
     65 
     66     respaddr.sin_family = AF_INET;
     67     respaddr.sin_addr.s_addr = INADDR_ANY;
     68     respaddr.sin_port = htons(port);
     69 
     70     if (bind(rsock, (struct sockaddr *) &respaddr, sizeof(respaddr))){
     71         perror("bind failed");
     72         exit(1);
     73     }
     74 
     75     // build request
     76     size_t len = strlen(av[1]);
     77     memcpy(buf, av[1], len);
     78     buf[len] = ' ';
     79     char *cursor = buf + len + 1;
     80     len = strlen(av[3]);
     81     memcpy(cursor, av[3], len);
     82     memcpy(cursor + len, " 0\r\n", strlen(" 0\r\n"));
     83     cursor += len + strlen(" 0\r\n");
     84 
     85     // send request
     86     if (sendto(sock, buf, cursor - buf, 0, (const struct sockaddr *)&server, sizeof(server)) < 0) {
     87         perror("send failed");
     88         close(sock);
     89         exit(1);
     90     }
     91     close(sock);
     92 
     93     // reveice server response
     94     struct sockaddr_in addr;
     95     socklen_t ln = sizeof(addr);
     96     rval = recvfrom(rsock, buf, sizeof(buf)-1/* -1 to add end of string before printing */, 0, (struct sockaddr *) &addr, &ln);
     97     close(rsock);
     98     if (addr.sin_addr.s_addr == server.sin_addr.s_addr && rval != -1 && rval != 0) {
     99         buf[rval] = 0;
    100         puts(buf);
    101     }
    102 }
    103