0

ターミナルで「./udpclientlocalhost9191」を実行した後、UDPクライアントの次のCコードをコンパイルします。「EnterText =」をHelloと入力しましたが、sendtoで次のようなエラーが表示されます。

Enter text: hello 
hello
 : error in sendto()guest-1SDRJ2@md-K42F:~/Desktop$ 

「」

注:他のターミナル./server 9191で、以下のように1番目のサーバーポートを開きます。サーバーコードにエラーはないと思います。udpクライアントがサーバーにメッセージを渡していない。スレッドを使用しない場合、メッセージは渡されますが、スレッドで実行する必要があります。

UDPクライアントコード:

/* simple UDP echo client */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <pthread.h>

#define STRLEN 1024

static void *readdata(void *);
static void *writedata(void *);
  int sockfd, n, slen;
struct sockaddr_in servaddr;
char sendline[STRLEN], recvline[STRLEN];

int main(int argc, char *argv[]) {
  pthread_t  readid,writeid;

  struct sockaddr_in servaddr;
  struct hostent *h;

  if(argc != 3) {
    printf("Usage: %s <proxy server ip> <port>\n", argv[0]);
    exit(0);
  }

  /* create hostent structure from  user entered host name*/
  if ( (h = gethostbyname(argv[1])) == NULL) {
    printf("\n%s: error in gethostbyname()", argv[0]);
    exit(0);
  }

  /* create server address structure */
  bzero(&servaddr, sizeof(servaddr)); /* initialize it */
  servaddr.sin_family = AF_INET;
  memcpy((char *) &servaddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
  servaddr.sin_port = htons(atoi(argv[2])); /* get the port number from argv[2]*/

  /* create a UDP socket: SOCK_DGRAM */
  if ( (sockfd = socket(AF_INET,SOCK_DGRAM, 0)) < 0) {
    printf("\n%s: error in socket()", argv[0]);
    exit(0);
  }


  pthread_create(&readid,NULL,&readdata,NULL);
  pthread_create(&writeid,NULL,&writedata,NULL);

  while(1)
  {
  };

  close(sockfd);
}

static void * writedata(void *arg)
 {
 /* get user input */
  printf("\nEnter text: ");

  do {
      if (fgets(sendline, STRLEN, stdin) == NULL) {
        printf("\n%s: error in fgets()");
        exit(0);
      }
      /* send a text */
      if (sendto(sockfd, sendline, sizeof(sendline), 0, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
          printf("\n%s: error in sendto()");
          exit(0);
      }
     }while(1);
}

static void * readdata(void *arg)
{
  /* wait for echo */
  slen = sizeof(servaddr);
  if ( (n = recvfrom(sockfd, recvline, STRLEN, 0, (struct sockaddr *) &servaddr, &slen)) < 0) {
      printf("\n%s: error in recvfrom()");
      exit(0);
  }

  /* null terminate the string */
  recvline[n] = 0;

  fputs(recvline, stdout);


}
4

1 に答える 1

1

問題は、と呼び出しの両方に同じsockaddr構造体 ( ) を使用していることです。これが最初に発生するため、受信したパックのソース アドレスに書き込む準備としてクリアします(1 つを受信すると、そのスレッドはパケットを待機しているカーネルでブロックされたままになります)。次に、呼び出しが発生すると、すべてゼロであるため、すぐに EINVAL が返されます。servaddrsendtorevfromrecvfromservaddrsendtosockaddr

sockaddrへの引数がrecvfrom入力ではなく OUTPUT であるという事実に混乱しているかもしれません。受信したパケットの送信元アドレスが入力されます (どこからでもかまいません)。特定の場所 (サーバー?) からのみパケットを受信したい場合は、返信後にアドレスを確認し、recvfrom別の場所から送信された場合はパケットを破棄して、再びループバックする必要がありrecvfromます。

于 2012-10-08T18:18:36.370 に答える