【问题标题】:Socket connect error in CC中的套接字连接错误
【发布时间】:2016-07-31 16:33:09
【问题描述】:

此服务器的目标是以相对简单的方式传输小文件。我已经完成了代码,它全部编译没有错误,当我尝试运行它时,服务器端没有问题,但是客户端在套接字绑定和分段错误中给出了错误。我想知道代码中的什么导致了这些问题。

服务器:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <string.h>
#include <unistd.h>
#include <crypt.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <netinet/ip.h>
void timestamp_ss()
{
  time_t current_time;
  char* log_time;

  log_time = ctime(&current_time);
  log_file_ss(log_time);
}
send_data(int sockfd, char info_to_send)
{
  char eof_buffer[4] = "\EOF";
  int sent_data, data_to_send;
  data_to_send = strlen(&info_to_send);

  while(data_to_send > 0)
  {
  sent_data = send(sockfd, &info_to_send, data_to_send, 0);
  if(sent_data == -1)
    perror("There was a problem in the sending of data!");
  data_to_send -= sent_data;
  info_to_send += sent_data;
  }
  send(sockfd, eof_buffer, 4, 0);
}
int recv_data(int sockfd, char *dest_buffer)
{
  #define EoF "\EOF"
  unsigned char *buffer;
  int eof_match = 0, eof_size = 2;

  buffer = dest_buffer;
  while(recv(sockfd, buffer, 1, 0) == 1)
  {
    if(*buffer == EoF[eof_match])
    {
      eof_match++;
      if(eof_match = eof_size)
        {
          *(buffer+1-eof_size) = '\0';
          return strlen(dest_buffer);
        }
        else
        {
          eof_match = 0;
        }
    }
    buffer++;
  }
  return 0;
}
int password_ss(char *password_attempt, char *password_actual)
{
  char key[] = { "ZjQXStSi" };
  char ivec[] = {"7eNP3U1b" };
  char des_dec[] = { "DES_DECRYPT" };
  char des_hw[] = { "DES_HW" };
  int l, i;

  l = strlen(password_attempt);
  i = cbc_crypt(key, password_attempt, l, *des_dec | *des_hw, ivec);
  if(i < 0)
    error_escape("In decryption");

  if(password_attempt == password_actual)
    return 1;
  else
    return 0;
}
int log_file_ss(char *log_message)
{
  char logfile[]= "/Server/log/C-File-Transfer-Server-Log";
  int log_fd, len;

  log_fd = open(logfile, O_WRONLY | O_APPEND | O_CREAT);
  len = strlen(log_message);
  write(log_fd, log_message, len);
}
void file_to_client_ss(int sockfd, struct sockaddr_in *client_addr_ptr)
{
  char file_req_c[128]; 
  char buffer[10000];
  char files[256];
  char pass_attempt[128];
  char *error_403[20] = { "Error 403: Forbidden" };
  char *error_404[25] = { "Error 404: File Not Found" };
  char *pass_path[20] = { "/server/log/PASSWORD" };
  char *pass_req[50] = { "This File Requires A Password, Please Enter It Now" };
  char *no_pass[37] = { "This File Does Not Require A Password" }; 
  char *username;
  char *file_s;
  char *string;
  char *file1_path[26] = { "/server/received_files/r_w" };
  char *file2_path[24] = { "/server/received_files/r" };
  char *file3_path[24] = { "/server/received_files/n" };
  char file_data;
  FILE *cs, *ps;
  int file1, file2, file3, file_test, pass;

  cs = fopen(file_req_c, "r");
  recv_data(sockfd, username);
  chdir("/server/log/PASSWORD");
  ps = fopen(username, "r");
  fread(files, 1, file_size(ps), ps);
  chdir("/server");
  recv_data(sockfd, file_req_c);
  file_test = file_exist(file1_path, file_req_c);
  if(file_test = -1)
  {
    file_test = file_exist(file2_path, file_req_c);
    if(file_test = -1)
    {
        file_test = file_exist(file3_path, file_req_c);
            if(file_test = -1)
            {
                error_escape("Opening file request from client");
            }
            else
            {
                    send_data(sockfd, **pass_req);
                    recv_data(sockfd, pass_attempt);
                    pass = password_ss(pass_attempt, files);
                        if(pass == 0)
                {
                            send_data(sockfd, **error_403);
                            error_escape("Wrong Password");
                }
                    else
                    {
                             if(file_exist(pass_path, username) == 0)
                                send_data(sockfd, *file_req_c);
                    else
                        errror_escape("Error in sending file");
                        }
            }   
       }
      else
      {
        chdir(*file2_path);
        file_data = fread(buffer, 1, file_size(cs), cs);
        send_data(sockfd, **no_pass);
        send_data(sockfd, file_data);
      }     
  }
  else
  {
    chdir(*file1_path);
    file_data = fread(buffer, 1, file_size(cs), cs);
    send_data(sockfd, **no_pass);
    send_data(sockfd, file_data);
  }
}
int file_size(FILE *stream)
{
  off_t file_len; 

  fseek(stream, 0, SEEK_END);
  file_len = ftell(stream);
  fclose(stream);
  return file_len;
}
int file_exist(char *file_path, char *file_name)
{
  DIR *dp;
  FILE *fc;
  struct dirent *ep;

 dp = opendir(file_path);

  if(dp == NULL)
    perror("Opening path");
  else
    chdir(file_path);
closedir(dp);

fc = fopen(file_name, "r");
  if(fc == NULL)
  {
    perror("Opening file");
    return(-1);
  }
  else {
    return(0);
}
}
error_escape(char *problem)
{
  char error_message[256];

  strcpy(error_message, "! There Has Been An Error !");
  strncat(error_message, problem, 173);
  perror("Error: ");
  log_file_ss(error_message);
  timestamp_ss();
  exit(-1);
}
void file_accept_ss(int sockfd, struct sockaddr_in *client_addr_ptr)
{
  char client_request[512], username[256], file_content[8192], buf[8192];
  char *client_r_w[26]  = { "/server/received_files/r_w" };
  char *client_r[24] = { "/server/received_files/r" }; 
  char *client_n[24] = { "/server/received_files/n" }; 
  char *search_string_read[6] = { "O_READ" };
  char *search_string_w[14] = { "O_READANDWRITE" };
  char *password_path[20] = { "/server/log/PASSWORD" };
  char *mkdir[37] = { "/server/log/PASSWORD" };
  char *ret;
  char file_data, recv_i;
  char password[256];
  int change_dir_test, recv_check;
  FILE *fn, *Ps;

  recv_data(sockfd, username);
  recv_data(sockfd, password);
  strcat(*mkdir, username);
  strcat(*mkdir, password);
  fn = fopen(*mkdir, "a");
  chdir(*password_path);
  Ps = fopen(*mkdir, "a");
  chdir("/server");
  recv_i = fread(buf, 1, file_size(fn), fn);
  recv_check = recv_data(sockfd, &recv_i);
  if(recv_check = -1)
    error_escape("! There Was An Error In The Receiving Of The File From The Client !");
  fread(file_content, 8, file_size(fn), fn);
  ret = strstr(file_content, *search_string_read);
  if(ret = NULL)
    {
    change_dir_test = chdir(*client_n);
      if(change_dir_test = -1)
        error_escape("! There Was An Error In The Changing Of Directories !");
       else
       {
    file_data = fread(buf, 1, file_size(Ps), Ps);
        recv_data(sockfd, &file_data);
        chdir(*client_n);
    strcat(*client_n, username);
        rename(username, *client_n);
       }
    }
  if(ret = *search_string_read)
    {
    change_dir_test = chdir(*client_r);
      if(change_dir_test = -1)
        error_escape("! There Was An Error In The Changing Of Directories !");
       else
       {
        chdir(*client_r);
        rename(username, *client_r);
       }
    }
  if(ret = *search_string_w)
    {
    change_dir_test = chdir(*client_r_w);
      if(change_dir_test = -1)
        error_escape("! There Was An Error In The Changing Of Directories !");
       else
       {
        chdir(*client_r_w);
        rename(username, *client_r_w);
    }
    }
  log_file_ss("Client:");
  log_file_ss(username);
  timestamp_ss();
}
int main(void)
{
  struct sockaddr_in server, client;
  int sockfd, bind_test, listen_test, client_sockfd, sin_size;

  sockfd = socket(PF_INET, SOCK_STREAM, 0);
  if(sockfd == -1)
    error_escape("Making Socket");

  server.sin_family = AF_INET;
  server.sin_port = htons(80);
  server.sin_addr.s_addr = INADDR_ANY;

  bind_test = bind(sockfd, (struct sockaddr *)&server, sizeof(server));
  if(bind_test < 0)
    error_escape("Binding Socket");
  listen_test = listen(sockfd, 20);
  if(listen_test < 0)
    error_escape("Listening");
  while(1)
  {
    sin_size = sizeof(struct sockaddr_in);
    client_sockfd = accept(sockfd, (struct sockaddr *)&client, &sin_size);
    file_accept_ss(client_sockfd, &client);
    file_to_client_ss(client_sockfd, &client);
  }
shutdown(client_sockfd, SHUT_RDWR);
return 0;
}

客户:

#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>
#include <crypt.h>
#include <sys/socket.h>
#include <netinet/ip.h>



send_data(int sockfd, char info_to_send)
{
  char eof_buffer[4] = "\EOF";
  int sent_data, data_to_send;
  data_to_send = strlen(&info_to_send);

  while(data_to_send > 0)
  {
  sent_data = send(sockfd, &info_to_send, data_to_send, 0);
  if(sent_data == -1)
    perror("There was a problem in the sending of data!");
  data_to_send -= sent_data;
  info_to_send += sent_data;
  }
  send(sockfd, eof_buffer, 4, 0);
}
send_file_cs(int sockfd)
{
  char file_buffer[4096], file_name[256];
  char name, username, password;
  char *search_st, file_data, *file_location;
  int perm_choice, password_max = 20, ch;
  off_t size_of_file;
  FILE *fp;

  printf("%s\n", "Please enter the path to file you would like to move to server:");
  scanf("%s", &file_location);
  ch = chdir(file_location);
  if(ch == -1)
    perror("! There Has Been An Error In The Directory Path !");
  else
    chdir(file_location);
  printf("%s\n", "Now Enter The Name Of The File You Would Like To Transfer:");
  printf("%s\n", "! Warning, The File May Not Exceed 4 kilobytes !");
  scanf("%s", &name);
  printf("%s", "What would you like the username for this file to be?");
  name = *file_name;
  size_of_file = file_size(fp);
  if(size_of_file > 4096)
    printf("! The File Is Greater Than 4 Kilobytes !");
  fp = fopen(file_name, "r+");
  printf("%s\n", "What Permissions Would You Like The File To Have?\n (1) For Other Clients To See The File\n (2) For Other CLients To See But Not Be Able To Access\n (3) Other Clients Cannot See Or Access The File");
  scanf("%d", &perm_choice);
  if(perm_choice > 3 || perm_choice < 1)
    perror("! Incorrect Permissions !");
  if(perm_choice = 1)
    {
    search_st = "O_READ";
    fopen(file_name, "a");
    fwrite(search_st, 1, strlen(search_st), fp);
    }
  if(perm_choice = 2)
    {
    search_st = "O_READANDWRITE";
    fopen(file_name, "a");
    fwrite(search_st, 1, strlen(search_st), fp);
    }
  if(perm_choice = 3)
    {
    search_st = "O_NOACCESS";
    fopen(file_name, "a");
    fwrite(search_st, 1, strlen(search_st), fp);
    printf("%s", "Please enter a password");
    scanf("%s", &password);
    send_data(sockfd, password);
    }
  file_data = fread(file_buffer, 1, 4096, fp);
  send_data(sockfd, file_data);
}       
int recv_data(int sockfd, char *dest_buffer)
{
  #define EoF "\EOF"
  unsigned char *buffer;
  int eof_match = 0, eof_size = 2;

  buffer = dest_buffer;
  while(recv(sockfd, buffer, 1, 0) == 1)
  {
    if(*buffer == EoF[eof_match])
    {
      eof_match++;
      if(eof_match = eof_size)
        {
          *(buffer+1-eof_size) = '\0';
          return strlen(dest_buffer);
        }
        else
        {
          eof_match = 0;
        }
    }
    buffer++;
  }
  return 0;
}
int password_cs(int max_length, int sockfd)
{
  char salt[] = { "ZjQXStSi" };
  char ivec[] = { "7eNP3U1b" };
  char des_enc[] = { "DES_ENCRYPT" };
  char des_hw[] = { "DES_HW" };
  char password;
  char *ret, *ret2;
  int l, i;

  printf("%s", "Please set your password:");
  scanf("%s", &password);
  l = strlen(&password);
  if(l > max_length)
    printf("%s : %d", "Password must be less than", max_length);

  i = cbc_crypt(salt, password, l, *des_enc | *des_hw, ivec);
  if(i < 0)
    perror("In erncryption");

  send_data(sockfd, password);
  return 0;
}
int file_size(FILE *stream)
{
  off_t file_len; 

  fseek(stream, 0, SEEK_END);
  file_len = ftell(stream);
  fclose(stream);
  return file_len;
}
int file_exist(char *file_path, char *file_name)
{
  DIR *dp;
  FILE *fc;
  struct dirent *ep;

 dp = opendir(file_path);

  if(dp == NULL)
    perror("Opening path");
  else
    chdir(file_path);
closedir(dp);

fc = fopen(file_name, "r");
  if(fc == NULL)
  {
    perror("Opening file");
    return(-1);
  }
  else {
    return(0);
}
}
void client_request_file_cs(int sockfd)
{
  char password_buf[128], file[4096], recv_file[256];
  char *requires[16] = { "Requires" }; 
  char *str, *restr, *file_contents, *name2, *path, *rebuf;
  char file_req, password, name, username;
  int test;
  FILE *re;

  printf("%s\n", "What file would you like from the server?");
  scanf("%s", &file_req);
  printf("%s", "What is the user name associated with the file?");
  scanf("%s", &username);
  send_data(sockfd, username);
  printf("%s\n", "Where Would You Like The File To Be Put, Please Enter The Path:");
  scanf("%s", &path);
  test = chdir(path);
  if(test == -1)
    printf("%s\n", "Invalid Path");
  printf("%s\n", "What Would You Like To Call The File?");
  scanf("%s", &name);
  name2 = &name;
  re = fopen(name2, "w");
  fread(file_contents, 1, file_size(re), re);
  send_data(sockfd, file_req);
  recv_data(sockfd, password_buf);
  printf("%s\n", password_buf);
  str = strstr(password_buf, *requires);
  if(str == NULL)
    recv_data(sockfd, file);
  else
  {
    scanf("%s", &password);
    send_data(sockfd, password);
  }
  recv_data(sockfd, rebuf);
  fwrite(rebuf, 1, sizeof(rebuf), re);
  fclose(re);
  restr = strstr(file_contents, "error_");
  if(restr != NULL)
    printf("%s\n", re);
}
int main(void) 
{
struct sockaddr_in client, server_addr;
int sockfd, connected;

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(80);

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
  printf("%s", "Error opening socket");

connected = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
if(connected == -1)
  printf("%s", "Error binding socket");

send_file_cs(sockfd);
client_request_file_cs(sockfd);
shutdown(sockfd, SHUT_RDWR);
return 0;
}

提前感谢您的帮助。

【问题讨论】:

  • 你有没有用调试器单步调试过这段代码?
  • 我找不到您如何在客户端代码中设置 server_addr.sin_addr.s_addr。看来您调用 connect 时地址未初始化,这很糟糕,但可能不是唯一的问题。
  • 似乎连接问题给出了错误“连接被拒绝”
  • 在这种情况下,最小、完整且可验证的示例如何必须是 2 个 C 文件、2 个程序中的 530 行代码?

标签: c sockets server


【解决方案1】:

绑定错误

这里没有绑定错误。客户端根本不做绑定。它收到一个错误connecting套接字,然后误导性地打印“绑定错误”。

连接错误是因为您没有初始化您尝试连接的目标的地址字段。

NB 你不需要\EOF。当对等方断开连接时,recv() 将返回零,您没有检查。您也没有检查它是否有错误。这是非常奇怪的代码。 – EJP 19 分钟前

【讨论】:

    【解决方案2】:

    在 cmets 中的其他有效问题/要点中,您的代码中的内存分配可能会导致您的分段错误...

    char *file_location(和其他)正在被使用,就像已分配内存一样。

    您在分配内存之前使用scanf("%s", &amp;file_location); 中的变量会调用未定义的行为,并且很可能(至少部分地)对您的运行时错误负责。

    在scanf 语句之前添加内存。以下是如何做到这一点的两个示例:

    1)创建堆内存(使用[m][c]alloc):

    char *file_location;    
    
    file_location = malloc(MAX_FILENAME_LEN);//or your systems value for max directory length
    if(file_location)
    {
        scanf("%s", &file_location);
        ...
    

    2)使用堆栈内存:(将指针指向有内存的地方)

     char file_name[256];
     char *file_location = file_name;
    
     file_location = file_name;
     scanf("%s", &file_location);
    

    但最简单的方法(如果没有什么限制您使用指针的话)是在堆栈上创建变量并在scanf(...) 中使用它:

    char file_location[256];
    
    scanf("%s", &file_location);
    

    您的示例代码中还有其他变量(file_location 除外)在使用前需要内存。使用完毕后,请记住释放所有创建了内存的变量on the heap

    【讨论】:

    • 在尝试了这两个之后,无论我输入什么地址,它仍然返回错误“错误地址”。
    • @WinnerInc - 我提供的内存创建问题/解决方案只是您的代码示例的几个潜在问题之一,在您让它运行之前需要解决这些问题。你有没有在任何地方初始化server_addr.sin_addr.s_addr?您是否尝试过自己使用调试器逐步完成它? (我会的,除非我现在离我的编译器不近)
    猜你喜欢
    • 2011-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-26
    • 1970-01-01
    • 1970-01-01
    • 2020-08-06
    • 2011-07-09
    相关资源
    最近更新 更多