Pregunta

He hecho C programas son el servidor y el cliente.Enviar mensaje de uno a otro mediante el uso de udp.

El servidor espera hasta que el mensaje se envía desde el cliente.

Cuando yo escriba algún mensaje desde la consola del cliente, el cliente enviará el mensaje al servidor.

El servicio recibe el mensaje desde el cliente, a continuación, el servidor le echo el mensaje en su consola y enviar de nuevo el mismo mensaje al cliente.

Finalmente, el cliente muestra mensaje en la consola que el servidor envía el mensaje.

En este procedimiento, el cliente muestra su número de puerto de origen en su consola.Y el servidor también se muestra al cliente el número de puerto de origen que el mensaje fue enviado con recvfrom ()

Extrañamente, el número de puerto de origen es diferente entre el cliente y el servidor si corro en windows7 pero si corro en CentOS6.4 el número de puerto de origen es el mismo.

¿Alguien sabe cómo sucede esto?

Mi código son los siguientes.

[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;
}

[cliente]

 #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);
}
¿Fue útil?

Solución

Es posible que un nuevo puerto de origen aleatorios se utiliza cada vez que se llame a sendto(), a menos que explícitamente bind() el socket de cliente a un determinado puerto de origen (y no confiar en el sistema operativo haciendo un implícita bind() para usted).Que es la única manera confiable para el cliente podría mostrar su propio puerto de origen, ya que sendto() no informe el puerto de origen que se utiliza realmente.Recuerde que, a diferencia de TCP, UDP es la conexión de menos, así que el puerto de origen no está obligado a permanecer constante a menos que a la fuerza.

Actualización:su código de cliente tiene una línea donde se hace el registro de un orden de byte de red número de puerto al que debe ser el registro de un orden de byte de host número de puerto en su lugar:

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

Aparte de eso, ¿por qué no crear su propia charToInt() la función, en lugar de utilizar una función estándar, como atoi() o strtol()?

Usted también no están haciendo muy buen manejo de errores.

Trate de algo más parecido a esto:

[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;
}

[Cliente]

#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;
}

Otros consejos

 return s.sin_port;

Que debe ser

return ntohs(s.sin_port);

Funciona en CentOS presumiblemente porque 'ntohs(i) == i' allí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top