Question

I’ve made C programs they are the server and the client. They send message each other by using udp.

The server waits until message is sent from the client.

When I type some message from the client console, the client will send the message to the server.

The serve receives the message from the client then the server will echo the message on its console and send back same message to the client.

Finaly the client shows message on its console that the server sent back the message.

In this procedure the client shows its source port number on its console.And the server also shows client's source port number that message was sent with recvfrom ()

Strangely, source port number is different between the client and the server if I run them on windows7 but if I run them on CentOS6.4 the source port number is same.

Does anyone know how this happens?

My code are following.

[server]

#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <sys/types.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string.h>
int charToInt(char myText[]) {
     char s[] = {'1', '2', '3', '4'};
     const int n = strlen(myText);
     int i, m = 0;

    for(i = 0; i < n; ++ i){
             m = m * 10 + myText[i] - '0';
    }
        printf("%d\n", m);
    return m;
 }
int
main(int argc,char *argv[])
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);

    int sock;
 struct sockaddr_in addr;
 struct sockaddr_in from;

 int sockaddr_in_size = sizeof(struct sockaddr_in);

 char buf[2048];
 char comnd[2048];
 char *bye="bye";

 printf("#############  udpServer start prot number is %d\n",charToInt(argv[1]));
 sock = socket(AF_INET, SOCK_DGRAM, 0);
 addr.sin_family = AF_INET;
 addr.sin_port = htons(charToInt(argv[1]));

 addr.sin_addr.s_addr = INADDR_ANY;
 bind(sock, (struct sockaddr *)&addr, sizeof(addr));

 while (!strncmp(buf,bye,3)==0){
        memset(buf, 0, sizeof(buf));
    recvfrom(sock, buf, sizeof(buf), 0,(struct sockaddr *)&from, &sockaddr_in_size);

    printf("recived '%s'(%d) from %s:%d\n", buf, strlen(buf),
                              inet_ntoa(from.sin_addr),ntohs(from.sin_port));

         sendto(sock, buf, sizeof(buf), 0, (struct sockaddr *)&from, sizeof(from));

        printf("send back %s to %s:%d\n", buf,inet_ntoa(from.sin_addr),ntohs(from.sin_port));
    printf("\n");
  } 
  printf("bye now");
  close(sock);
  return 0;
}

[client]

 #define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <sys/types.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string.h>
#include <errno.h>
int charToInt(char myText[]) {
     char s[] = {'1', '2', '3', '4'};
     const int n = strlen(myText);
     int i, m = 0;

    for(i = 0; i < n; ++ i){
             m = m * 10 + myText[i] - '0';
    }
        printf("%d\n", m);
    return m;
 }

 int getMyPortNum(int sock)
{
    struct sockaddr_in s;
    socklen_t sz = sizeof(s);
    getsockname(sock, (struct sockaddr *)&s, &sz);
    return s.sin_port;
}

int
main(int agrc,char *argv[])
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);

    char *host;
    int port;
    int sock;
 struct sockaddr_in dst_addr = {0};
 struct sockaddr_in src_addr = {0};
 struct sockaddr_in rcv_addr = {0};

 int sockaddr_in_size = sizeof(struct sockaddr_in);
 int defPortNum;


 char message[2048];
 char comnd[2048];
 int i;
 int ret;
 int connect_ret;
 int bind_ret;
 char *p;
 char buf[2048];

 host=argv[1];
 port=charToInt(argv[2]);

 printf("host = %s\n",host);
 printf("port = %d\n",port);
 sock = socket(AF_INET, SOCK_DGRAM, 0);

 dst_addr.sin_family = AF_INET;
 dst_addr.sin_addr.s_addr = inet_addr(host);
 dst_addr.sin_port = htons(port);

 printf("getMyPortNum before bind() is %d\n",ntohs(src_addr.sin_port));

 bind_ret = 0;

 bind_ret = bind(sock,(struct sockaddr *)&src_addr,sizeof(src_addr));
    src_addr.sin_port = getMyPortNum(sock);

 printf("Default Client port is %d\n",ntohs(src_addr.sin_port));
 if(bind_ret>=0){
    printf("bind() error ret = %d:%s\n",bind_ret,strerror(errno));
    perror("bind()");
    return bind_ret;
 } 

 memset(message, 0, sizeof(message));
 memset(comnd, 0, sizeof(comnd));
 memset(buf,0,sizeof(buf));

 while(!strncmp(comnd,"bye",3)==0){
    if(strncmp(message,"bye",3)==0){
        strcpy(comnd,message);
    }else{
            printf("typ your message (exit:stop Client bye:stop server)>>>\t"); 
        fgets(comnd,sizeof(comnd),stdin);
        comnd[strlen(comnd) - 1] = '\0'; 
        strcpy(message,comnd);
    }
    ret = sendto(sock, message, strlen(message), 0,
             (struct sockaddr *)&dst_addr, sizeof(dst_addr));
    printf("Server port (dst port) for sending is %d\n",ntohs(dst_addr.sin_port));
    if(ret<0){
        printf("Send Error ret = %d:%s\n",ret,strerror(errno));
        return ret;
    }else{
        printf("Waiting for sendBack !!!\n");
        printf("Client port for recieving  is %s:%d\n"
                ,inet_ntoa(src_addr.sin_addr),ntohs(src_addr.sin_port));
        ret = recvfrom(sock, buf, sizeof(buf), 
                0,(struct sockaddr *)&rcv_addr, &sockaddr_in_size); 
        if(ret<0){
            printf("ReciveError ret = %d\n",ret);
        }else{
            printf("Sentback %s from %s:%d\n"
                    ,buf,inet_ntoa(rcv_addr.sin_addr)
                    ,ntohs(rcv_addr.sin_port));
        }
    }
 }
 close(sock);
}
Was it helpful?

Solution

It is possible that a new random source port gets used every time you call sendto(), unless you explicitly bind() the client socket to a specific source port (and not rely on the OS doing an implicit bind() for you). That is the only reliable way the client could display its own source port, since sendto() does not report the source port that is actually used. Remember, unlike TCP, UDP is connection-less, so the source port is not required to stay consistent unless you force it.

Update: your client code has one line where it is logging a network byte order port number when it should be logging a host byte order port number instead:

//printf("getMyPortNum before bind() is %d\n",myName.sin_port);
printf("getMyPortNum before bind() is %d\n",port);

Aside from that, why did you create your own charToInt() function, instead of using a standard function, like atoi() or strtol()?

You are also not doing very good error handling.

Try something more like this instead:

[Server]

#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <sys/types.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

int printerror2(char func[], int errnum)
{
    printf("%s error = %d:%s\n", func, errnum, strerror(errnum));
    perror(func);
    return errnum;
}

int printerror(char func[])
{
    return printerror2(func, errno);
}

int main(int argc, char *argv[])
{
    WSADATA wsaData;
    int ret = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (ret != 0)
        return printerror2("WSAStartup()", ret);

    int sock;
    in_port_t port;
    struct sockaddr_in addr;
    struct sockaddr_in from;
    int from_size;

    char buf[2048];

    port = atoi(argv[1]);
    printf("############# udpServer port number is %hu\n", port);

    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sock == -1)
        return printerror("socket()");

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;

    ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
    if (ret == -1)
        return printerror("bind()");

    do
    {
        from_size = sizeof(from);

        ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&from, &from_size);
        if (ret == -1)
            return printerror("recvfrom()");

        printf("received '%*s'(%d) from %s:%hu\n",
            ret, buf, ret, inet_ntoa(from.sin_addr), ntohs(from.sin_port));

        ret = sendto(sock, buf, ret, 0, (struct sockaddr *)&from, from_size);
        if (ret == -1)
            return printerror("sendto()");

        printf("sent back '%*s'(%d) to %s:%hu\n",
            ret, buf, ret, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
        printf("\n");
    } 
    while ((ret != 3) || (strncmp(buf, "bye", 3) != 0));

    printf("bye now");

    close(sock);
    return 0;
}

[Client]

#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <sys/types.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

int printerror2(char func[], int errnum)
{
    printf("%s error = %d:%s\n", func, errnum, strerror(errnum));
    perror(func);
    return errnum;
}

int printerror(char func[])
{
    return printerror2(func, errno);
}

int getMyPortNum(int sock, in_port_t *port)
{
    struct sockaddr_in s;
    socklen_t sz = sizeof(s);
    int ret = getsockname(sock, (struct sockaddr *)&s, &sz);
    if (ret == 0)
       *port = s.sin_port;
    return ret;
}

int main(int agrc, char *argv[])
{
    WSADATA wsaData;
    int ret = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (ret != 0)
        return printerror2("WSAStartup", ret);

    char *host;
    in_port_t port;
    int sock;
    struct sockaddr_in dst_addr;
    struct sockaddr_in src_addr;
    struct sockaddr_in from_addr;
    int from_size;

    char buf[2048];

    host = argv[1];
    port = atoi(argv[2]);

    printf("host = %s\n", host);
    printf("port = %hu\n", port);

    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sock == -1)
        return printerror("socket()");

    memset(&src_addr, 0, sizeof(src_addr));
    src_addr.sin_family = AF_INET;
    src_addr.sin_addr.s_addr = INADDR_ANY;
    src_addr.sin_port = 0;

    ret = bind(sock, (struct sockaddr *)&src_addr, sizeof(src_addr));
    if (ret == -1)
        return printerror("bind()");

    ret = getMyPortNum(sock, &(src_addr.sin_port));
    if (ret == -1)
        return printerror("getsockname()");

    printf("Client port is %hu\n", ntohs(src_addr.sin_port));

    memset(&dst_addr, 0, sizeof(dst_addr));
    dst_addr.sin_family = AF_INET;
    dst_addr.sin_addr.s_addr = inet_addr(host);
    dst_addr.sin_port = htons(port);

    do
    {
        printf("type your message (exit: stop Client, bye: stop server)>>>\t"); 
        fgets(buf, sizeof(buf), stdin);

        if (strcmp(buf, "exit") == 0)
            break;

        ret = sendto(sock, buf, strlen(buf), 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr));
        if (ret == -1)
            return printerror("sendto()");

        printf("Waiting for send back !!!\n");

        from_size = sizeof(from_addr);

        ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&from_size, &from_size); 
        if (ret == -1)
            return printerror("recvfrom()");

        printf("Received '%*s' from %s:%hu\n",
            ret, buf, inet_ntoa(from_addr.sin_addr), ntohs(from_addr.sin_port));
    }
    while ((ret != 3) || (strncmp(buf, "bye", 3) != 0));

    close(sock);
    return 0;
}

OTHER TIPS

 return s.sin_port;

That should be

return ntohs(s.sin_port);

It works in CentOS presumably because 'ntohs(i) == i' there.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top