开发者

Issues while using SOCK_DGRAM to get information from server

开发者 https://www.devze.com 2023-01-29 08:35 出处:网络
I have the following program (DGRAM Sockets) to retreive the time from a time server . The program does not print out the current time as expected.

I have the following program (DGRAM Sockets) to retreive the time from a time server . The program does not print out the current time as expected.

#define DAYTIME_SERVER_PORT  13

int main(int argc, char *argv[])
{

    int connectionFd, in;
    struct sockaddr_in servaddr;
    char buf[BUFSIZ];

    connectionFd = socket(AF_INET, SOCK_DGRAM, 0);
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(DAYTIME_SERVER_PORT);
    inet_pton(AF_INET,"time.mit.edu", &servaddr.sin_addr);

    sendto( connectionFd,buf ,1, 0,(struct sockaddr_in *)&servaddr, sizeof(servaddr) );

    in = recv(connectionFd, buf, BUFSIZ, 0 ) ; 
    buf[in] = 0 ; 
    printf("Time is %s \n",buf);

    close(c开发者_Go百科onnectionFd);


}

My Questions are - Where am I making a mistake ? Any code changes and valuable suggestions are appreciated. I am not sure about how to use the recvform function and hence tried a recv. The daytime server I am connecting to is time.mit.edu


inet_pton() does not look up host names like time.mit.edu. It is just for converting the string form of an IP address, like "18.7.21.144", into a socket address.

You should use getaddrinfo() to look up a name like "time.mit.edu". It can also do the job of looking up the daytime port number. Your code would look like:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main(int argc, char *argv[])
{
    struct addrinfo *addr;
    struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM };
    int err;
    int connectionFd, in;
    char buf[1024];

    err = getaddrinfo("time.mit.edu", "daytime", &hints, &addr);
    if (err) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
        return 1;
    }

    connectionFd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);

    sendto(connectionFd, "." , 1, 0, addr->ai_addr, addr->ai_addrlen );

    freeaddrinfo(addr);

    in = recv(connectionFd, buf, sizeof buf - 1, 0 ) ;
    buf[in] = 0 ;
    printf("Time is %s \n",buf);

    close(connectionFd);
    return 0;
}

(Look, Ma: IPv6-capable daytime ;)

Of course, you should also be checking the return value of socket(), sendto() and recv(), just like I did for getaddrinfo(). In particular, consider what happens if recv() fails and returns -1...


You check neither the return value of the socket(2), sendto(2), nor the recv(2) functions, which return -1 on error and set global errno(3) variable. Make a habit of always checking what system calls return.

You give the recv() the BUFSIZ as available space, then write to the byte one after the received length. This might not really be a problem if BUFSIZ is really large (larger then any UDP datagram, i.e. 2^16), but you might be overrunning the buffer if you receive full buf-worth of data.

As for the real problem in your code - @caf already answered that.


Your code is essentially correct. I had to tweak it a bit because I'm running Windows, but it works for me. So here are some things you could look at:

  • What's the return value from sendto? That might tell you at least whether you're connecting OK.

  • Check that your address is correct. It might be easier to hard-code the IP address of time.mit.edu directly into servaddr.sin_addr, to remove any possibility that inet_pton is causing a problem.

  • What value is BUFSIZ? Normally it's set in stdio.h but are you sure it's not zero somehow?

  • You don't set the protocol explicitly to IPPROTO_UDP. That's normally OK because your sockets library will choose an appropriate protocol when you set protocol=0. Use getsockopt(SO_PROTOCOL_INFO) to check that it's correct (or set it explicitly in your call to socket()).

  • Is your firewall getting in the way? Try telneting to time.mit.edu:13. It should print out the time and then close the connection.

About recvfrom... it's the same as recv except that it captures the address of the peer host. That difference isn't material here.

0

精彩评论

暂无评论...
验证码 换一张
取 消