来自C语言中sendto()套接字程序的无效参数

时间:2018-09-13 15:43:20

标签: c sockets client-server unix-socket

我正在尝试制作一个简单的客户端服务器API,用于我的两台计算机。我编写了这个简单的程序,使用了我测试的功能。由于某种原因,我的客户端发送的消息很好,但是我的服务器却不能(但是,它从客户端接收到该消息)。

服务器端输出:

 host name: my_host
 Our port number is: 34440
 Client msg: Client msg
 Send failed: Invalid argument
 Message from Server sent to Client

客户端输出:

 Connection established with server...
 Message from Client sent to Server

服务器端:

#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include "my_socket.h"

int main() {

    server_init();
    char *msg = "Server msg";
    char buffer[100];

    int n = read_from_client((char *)buffer);
    buffer[n] = '\0';
    printf("Client msg: %s\n", buffer);
    write_to_client((char *)msg);
    printf("Message from Server sent to Client \n");   
    return 0;
}

客户端:

   #include <sys/socket.h>
   #include <stdio.h>
   #include <unistd.h>
   #include <fcntl.h>
   #include <pthread.h>
   #include <stdlib.h>
   #include "my_socket.h"

   int main() {

   client_init();
   char *msg = "Client msg";
   char buffer[100];

   write_to_server((char*)msg);
   printf("Message from Client sent to Server \n");
   int n = read_from_server((char *)buffer);
   buffer[n] = '\0';
   printf("Server msg: %s\n", buffer);

   close_socket();  
   return 0;
 }

my_socket.c:

#include "my_socket.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>

   int sockfd1;
   int sockfd2;
   int MAX_BUFF = 1024;
   struct sockaddr_in server;
   struct sockaddr_in client;
   struct hostent *host;

   ssize_t write_to_server(const void *buffer){
      int bytes_sent, server_size = sizeof(server), buf_len = strlen(buffer);
      if ((bytes_sent = sendto(sockfd2, buffer, buf_len, 0, 
            (const struct sockaddr *)&server, server_size)) < 0){
     perror("Send failed");
      }
      return bytes_sent;
   }

   ssize_t write_to_client(const void *buffer){
      int bytes_sent, client_size = sizeof(client), buf_len = strlen(buffer);
      if ((bytes_sent = sendto(sockfd1, buffer, buf_len, 0, 
            (const struct sockaddr *)&client, client_size)) < 0){
     perror("Send failed");
      }
      return bytes_sent;
   }

   int read_from_server(void *buffer){
      int bytes_rcv, len;
      if ((bytes_rcv = recvfrom(sockfd2, buffer, MAX_BUFF, MSG_WAITALL, 
                   (struct sockaddr *)&server, &len)) < 0){
     perror("Read failed");
      }
      return bytes_rcv;
   }

   int read_from_client(void *buffer){
      int bytes_rcv, len;
      if ((bytes_rcv = recvfrom(sockfd1, buffer, MAX_BUFF, MSG_WAITALL, 
                   (struct sockaddr *)&client, &len)) < 0){
     perror("Read failed");
      }
      return bytes_rcv;
   }


   void close_socket() {
      close(sockfd1);
      close(sockfd2);
   }

   void server_init(){
      if ( (sockfd1 = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
     perror("socket creation failed");
      }
      char name[1024];
      name[1023] = '\0';
      gethostname(name, 1023);
      printf("host name: %s \n", name);

      host = gethostbyname("my_host");
      if(host == NULL){
     perror("Host is null");
     exit(0);
      }

      bzero((char *)&server, sizeof(server));
      bzero((char *)&client, sizeof(client));

      server.sin_family          = AF_INET;
      bcopy((char *)host->h_addr, 
        (char *)&server.sin_addr.s_addr, host->h_length);
      //server.sin_port            = 0; 
      server.sin_port            = htons(34440);

      if ( (bind(sockfd1, (struct sockaddr *)&server, sizeof(server) ) ) < 0 ){
     perror("bind failed");
      } 
      socklen_t len = sizeof(server);
      if (getsockname(sockfd1, (struct sockaddr *)&server, &len) == -1){
     perror("getsockname");
      }else{
     printf("Our port number is: %d\n", ntohs(server.sin_port));
      }
   }

   void client_init(){

      if ( (sockfd2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
     perror("socket creation failed");
      }

      host = gethostbyname("my_host");
      if(host == NULL){
     perror("Host is null");
     exit(0);
      }

      bzero((char *)&server, sizeof(server));

      server.sin_family       = AF_INET;
      bcopy((char *)host->h_addr, 
        (char *)&server.sin_addr.s_addr, host->h_length);
      //server.sin_port = 0; 
      server.sin_port = htons(34440);

      if(connect(sockfd2, (struct sockaddr *)&server, sizeof(server)) == 0){
     printf("Connection established with server...\n");
      }

   }

my_socket.h:

#ifndef MY_SOCKET
#define MY_SOCKET
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <netinet/in.h>
#include <netdb.h>


extern int sockfd1;
extern int sockfd2;
extern int MAX_BUFF;
extern struct sockaddr_in server;
extern struct sockaddr_in client;
extern struct hostent *host;


// Send a message over the socket  
ssize_t write_to_server(const void *buffer);
ssize_t write_to_client(const void *buffer);

// Blocks until told it's ready; receives bytes from socket 
int read_from_server(void *buffer);
int read_from_client(void *buffer);   

// Close the socket
void close_socket();

void server_init();

void client_init();      


#endif

欢迎任何建议或批评。预先感谢。

1 个答案:

答案 0 :(得分:2)

至少一个问题是您没有初始化len中的read_from_client变量。 recvfrom的手册页部分说(强调):

  

... addrlen是一个值结果参数。 在调用之前,应将其初始化为与src_addr关联的缓冲区的大小。返回时,addrlen将更新为包含源地址的实际大小。如果提供的缓冲区太小,返回的地址将被截断。在这种情况下,addrlen将返回一个大于提供给调用的值。

这意味着,len作为未初始化的堆栈变量,具有不确定的值。可能为零,但至少比sizeof(struct sockaddr_in)小。结果,client无法正确填充recvfrom

recvfrom之前,您应该使用以下命令对其进行初始化:

len = sizeof(client);

在客户端,write_to_serverread_from_server不需要使用recvfromsendto,因为您已经在套接字上完成了connect。他们可以简单地使用recvsend,因为connect已经建立了远程套接字端点。我相信对于连接的套接字,该地址只是被忽略了,但是我现在找不到在哪里记录。

(无论如何,如果您继续在客户端上使用recvfrom,则应该在客户端进行相同的len初始化。)