2017-2018-1 20155213陆忠民 实验三 实时系统报告

2017-2018-1 20155213陆忠民 实验三 实时系统报告

任务一:

学习使用Linux命令wc(1)
基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端
客户端传一个文本文件给服务器
服务器返加文本文件中的单词数

wc命令的功能为统计指定文件中的字节数、字数、行数,并将统计结果显示输出。

语法:wc [选项] 文件...

说明:该命令统计指定文件中的字节数、字数、行数。如果没有给出文件名,则从标准输入读取。wc同时也给出所指定文件的总统计数。下面让我们来简单的看一下其支持的参数及其代表的含义。

参数及含义

参数 含义
-c 显示文件的Bytes数(字节数)及文件名输出到屏幕上
-l 将每个文件的行数及文件名输出到屏幕上
-m 将每个文件的字符数及文件名输出到屏幕上,如果当前系统不支持多字节字符其将显示与-c参数相同的结果
-w 将每个文件含有多少个词及文件名输出到屏幕上
  • man指令查看wc

  • 在linux下面找到的wc源码,分析其中的输出单词数部分代码如下:
wc (int fd, char const *file_x, struct fstatus *fstatus)
{
  bool ok = true;
  char buf[BUFFER_SIZE + 1];
  size_t bytes_read;
  uintmax_t lines, words, chars, bytes, linelength;
  bool count_bytes, count_chars, count_complicated;
  char const *file = file_x ? file_x : _("standard input");

  lines = words = chars = bytes = linelength = 0;

  /* If in the current locale, chars are equivalent to bytes, we prefer
     counting bytes, because that's easier.  */
#if MB_LEN_MAX > 1
  if (MB_CUR_MAX > 1)
    {
      count_bytes = print_bytes;
      count_chars = print_chars;
    }
  else
#endif
    {
      count_bytes = print_bytes || print_chars;
      count_chars = false;
    }
  count_complicated = print_words || print_linelength;

  /* When counting only bytes, save some line- and word-counting
     overhead.  If FD is a `regular' Unix file, using lseek is enough
     to get its `size' in bytes.  Otherwise, read blocks of BUFFER_SIZE
     bytes at a time until EOF.  Note that the `size' (number of bytes)
     that wc reports is smaller than stats.st_size when the file is not
     positioned at its beginning.  That's why the lseek calls below are
     necessary.  For example the command
     `(dd ibs=99k skip=1 count=0; ./wc -c) < /etc/group'
     should make wc report `0' bytes.  */

  if (count_bytes && !count_chars && !print_lines && !count_complicated)
    {
      off_t current_pos, end_pos;

      if (0 < fstatus->failed)
        fstatus->failed = fstat (fd, &fstatus->st);

      if (! fstatus->failed && S_ISREG (fstatus->st.st_mode)
          && (current_pos = lseek (fd, (off_t) 0, SEEK_CUR)) != -1
          && (end_pos = lseek (fd, (off_t) 0, SEEK_END)) != -1)
        {
          /* Be careful here.  The current position may actually be
             beyond the end of the file.  As in the example above.  */
          bytes = end_pos < current_pos ? 0 : end_pos - current_pos;
        }
      else
        {
          while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
            {
              if (bytes_read == SAFE_READ_ERROR)
                {
                  error (0, errno, "%s", file);
                  ok = false;
                  break;
                }
              bytes += bytes_read;
            }
        }
    }
  else if (!count_chars && !count_complicated)
    {
      /* Use a separate loop when counting only lines or lines and bytes --
         but not chars or words.  */
      while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
        {
          char *p = buf;

          if (bytes_read == SAFE_READ_ERROR)
            {
              error (0, errno, "%s", file);
              ok = false;
              break;
            }

          while ((p = memchr (p, '\n', (buf + bytes_read) - p)))
            {
              ++p;
              ++lines;
            }
          bytes += bytes_read;
        }
    }
#if MB_LEN_MAX > 1
# define SUPPORT_OLD_MBRTOWC 1
  else if (MB_CUR_MAX > 1)
    {
      bool in_word = false;
      uintmax_t linepos = 0;
      DECLARE_ZEROED_AGGREGATE (mbstate_t, state);
      bool in_shift = false;
# if SUPPORT_OLD_MBRTOWC
      /* Back-up the state before each multibyte character conversion and
         move the last incomplete character of the buffer to the front
         of the buffer.  This is needed because we don't know whether
         the `mbrtowc' function updates the state when it returns -2, -
         this is the ISO C 99 and glibc-2.2 behaviour - or not - amended
         ANSI C, glibc-2.1 and Solaris 5.7 behaviour.  We don't have an
         autoconf test for this, yet.  */
      size_t prev = 0; /* number of bytes carried over from previous round */
# else
      const size_t prev = 0;
# endif

      while ((bytes_read = safe_read (fd, buf + prev, BUFFER_SIZE - prev)) > 0)
        {
          const char *p;
# if SUPPORT_OLD_MBRTOWC
          mbstate_t backup_state;
# endif
          if (bytes_read == SAFE_READ_ERROR)
            {
              error (0, errno, "%s", file);
              ok = false;
              break;
            }

          bytes += bytes_read;
          p = buf;
          bytes_read += prev;
          do
            {
              wchar_t wide_char;
              size_t n;

              if (!in_shift && is_basic (*p))
                {
                  /* Handle most ASCII characters quickly, without calling
                     mbrtowc().  */
                  n = 1;
                  wide_char = *p;
                }
              else
                {
                  in_shift = true;
# if SUPPORT_OLD_MBRTOWC
                  backup_state = state;
# endif
                  n = mbrtowc (&wide_char, p, bytes_read, &state);
                  if (n == (size_t) -2)
                    {
# if SUPPORT_OLD_MBRTOWC
                      state = backup_state;
# endif
                      break;
                    }
                  if (n == (size_t) -1)
                    {
                      /* Remember that we read a byte, but don't complain
                         about the error.  Because of the decoding error,
                         this is a considered to be byte but not a
                         character (that is, chars is not incremented).  */
                      p++;
                      bytes_read--;
                      continue;
                    }
                  if (mbsinit (&state))
                    in_shift = false;
                  if (n == 0)
                    {
                      wide_char = 0;
                      n = 1;
                    }
                }
              p += n;
              bytes_read -= n;
              chars++;
              switch (wide_char)
                {
                case '\n':
                  lines++;
                  /* Fall through. */
                case '\r':
                case '\f':
                  if (linepos > linelength)
                    linelength = linepos;
                  linepos = 0;
                  goto mb_word_separator;
                case '\t':
                  linepos += 8 - (linepos % 8);
                  goto mb_word_separator;
                case ' ':
                  linepos++;
                  /* Fall through. */
                case '\v':
                mb_word_separator:
                  words += in_word;
                  in_word = false;
                  break;
                default:
                  if (iswprint (wide_char))
                    {
                      int width = wcwidth (wide_char);
                      if (width > 0)
                        linepos += width;
                      if (iswspace (wide_char))
                        goto mb_word_separator;
                      in_word = true;
                    }
                  break;
                }
            }
          while (bytes_read > 0);

# if SUPPORT_OLD_MBRTOWC
          if (bytes_read > 0)
            {
              if (bytes_read == BUFFER_SIZE)
                {
                  /* Encountered a very long redundant shift sequence.  */
                  p++;
                  bytes_read--;
                }
              memmove (buf, p, bytes_read);
            }
          prev = bytes_read;
# endif
        }
      if (linepos > linelength)
        linelength = linepos;
      words += in_word;
    }
#endif
  else
    {
      bool in_word = false;
      uintmax_t linepos = 0;

      while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
        {
          const char *p = buf;
          if (bytes_read == SAFE_READ_ERROR)
            {
              error (0, errno, "%s", file);
              ok = false;
              break;
            }

          bytes += bytes_read;
          do
            {
              switch (*p++)
                {
                case '\n':
                  lines++;
                  /* Fall through. */
                case '\r':
                case '\f':
                  if (linepos > linelength)
                    linelength = linepos;
                  linepos = 0;
                  goto word_separator;
                case '\t':
                  linepos += 8 - (linepos % 8);
                  goto word_separator;
                case ' ':
                  linepos++;
                  /* Fall through. */
                case '\v':
                word_separator:
                  words += in_word;
                  in_word = false;
                  break;
                default:
                  if (isprint (to_uchar (p[-1])))
                    {
                      linepos++;
                      if (isspace (to_uchar (p[-1])))
                        goto word_separator;
                      in_word = true;
                    }
                  break;
                }
            }
          while (--bytes_read);
        }
      if (linepos > linelength)
        linelength = linepos;
      words += in_word;
    }

  if (count_chars < print_chars)
    chars = bytes;

  write_counts (lines, words, chars, bytes, linelength, file_x);
  total_lines += lines;
  total_words += words;
  total_chars += chars;
  total_bytes += bytes;
  if (linelength > max_line_length)
    max_line_length = linelength;

  return ok;
}
  • 通过读取按字节读取文件内容,之后一个字节一个字节的判断,整体最有有价值的就是:
switch (*p++)
                {
                case '\n':
                  lines++;
                  /* Fall through. */
                case '\r':
                case '\f':
                  if (linepos > linelength)
                    linelength = linepos;
                  linepos = 0;
                  goto word_separator;
                case '\t':
                  linepos += 8 - (linepos % 8);
                  goto word_separator;
                case ' ':
                  linepos++;
                  /* Fall through. */
                case '\v':
                word_separator:
                  words += in_word;
                  in_word = false;
                  break;
                default:
                  if (isprint (to_uchar (p[-1])))
                    {
                      linepos++;
                      if (isspace (to_uchar (p[-1])))
                        goto word_separator;
                      in_word = true;
                    }
                  break;
                }
  • mywc函数如下
int mywc(FILE*fp1)
{
int count=0;
    char s[21];
    if((fp1))==NULL){
        printf("Open the file failure...\n");
        exit(0);
    }
    while(fscanf(fp,"%s",s)!=EOF)
        count++;
        return count;
}
客户端代码:
/*************************************************************************
  > File Name: Client.c
  > Author: SongLee
 ************************************************************************/

#include<netinet/in.h>  // sockaddr_in
#include<sys/types.h>  // socket
#include<sys/socket.h>  // socket
#include<stdio.h>    // printf
#include<stdlib.h>    // exit
#include<string.h>    // bzero

#define SERVER_PORT 8000
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512

int main()
{
  // 声明并初始化一个客户端的socket地址结构
  struct sockaddr_in client_addr;
  bzero(&client_addr, sizeof(client_addr));
  client_addr.sin_family = AF_INET;
  client_addr.sin_addr.s_addr = htons(INADDR_ANY);
  client_addr.sin_port = htons(0);

  // 创建socket,若成功,返回socket描述符
  int client_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
  if(client_socket_fd < 0)
  {
    perror("Create Socket Failed:");
    exit(1);
  }

  // 绑定客户端的socket和客户端的socket地址结构 非必需
  if(-1 == (bind(client_socket_fd, (struct sockaddr*)&client_addr, sizeof(client_addr))))
  {
    perror("Client Bind Failed:");
    exit(1);
  }

  // 声明一个服务器端的socket地址结构,并用服务器那边的IP地址及端口对其进行初始化,用于后面的连接
  struct sockaddr_in server_addr;
  bzero(&server_addr, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  if(inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) == 0)
  {
    perror("Server IP Address Error:");
    exit(1);
  }
  server_addr.sin_port = htons(SERVER_PORT);
  socklen_t server_addr_length = sizeof(server_addr);

  // 向服务器发起连接,连接成功后client_socket_fd代表了客户端和服务器的一个socket连接
  if(connect(client_socket_fd, (struct sockaddr*)&server_addr, server_addr_length) < 0)
  {
    perror("Can Not Connect To Server IP:");
    exit(0);
  }

  // 输入文件名 并放到缓冲区buffer中等待发送
  char file_name[FILE_NAME_MAX_SIZE+1];
  bzero(file_name, FILE_NAME_MAX_SIZE+1);
  printf("Please Input File Name On Server:\t");
  scanf("%s", file_name);

  char buffer[BUFFER_SIZE];
  bzero(buffer, BUFFER_SIZE);
  strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE?BUFFER_SIZE:strlen(file_name));

  // 向服务器发送buffer中的数据
  if(send(client_socket_fd, buffer, BUFFER_SIZE, 0) < 0)
  {
    perror("Send File Name Failed:");
    exit(1);
  }

  // 打开文件,准备写入
  FILE *fp = fopen(file_name, "r");
  if(NULL == fp)
  {
    printf("File:\t%s Can Not Open To Write\n", file_name);
    exit(1);
  }

  // 从服务器接收数据到buffer中
  // 每接收一段数据,便将其写入文件中,循环直到文件接收完并写完为止
  bzero(buffer, BUFFER_SIZE);
  int length = 0;
  while((length = fread(buffer, sizeof(char), 1024, fp)) > 0)
      {
        if(send(client_socket_fd, buffer, length, 0) < 0)
        {
          printf("Send File:%s Failed./n", file_name);
          break;
        }
        bzero(buffer, BUFFER_SIZE);
      }
char ch[1024];
scanf("%s",ch);
send(client_socket_fd, "bye", 1024, 0);
	recv(client_socket_fd, buffer, 1024, 0);
    printf("There is(are) %s word(s) in the text %s.\n",buffer,file_name);
  // 接收成功后,关闭文件,关闭socket
  printf("Receive File:\t%s From Server IP Successful!\n", file_name);
  
  close(client_socket_fd);
  return 0;
}

服务器代码

/*************************************************************************
  > File Name: Server.c
  > Author: SongLee
 ************************************************************************/

#include<netinet/in.h> // sockaddr_in
#include<sys/types.h>  // socket
#include<sys/socket.h> // socket
#include<stdio.h>    // printf
#include<stdlib.h>   // exit
#include<string.h>   // bzero

#define SERVER_PORT 8000
#define LENGTH_OF_LISTEN_QUEUE 20
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512

void itoa(int i,char* string)
{
    int power,j;
    j=i;
    for(power=1;j>=10;j/=10)
        power*=10;
    for(;power>0;power/=10)
    {
        *string++='0'+i/power;
        i%=power;
    }
    *string='\0';
}

int main(void)
{
  // 声明并初始化一个服务器端的socket地址结构
  struct sockaddr_in server_addr;
  bzero(&server_addr, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = htons(INADDR_ANY);
  server_addr.sin_port = htons(SERVER_PORT);

  // 创建socket,若成功,返回socket描述符
  int server_socket_fd = socket(PF_INET, SOCK_STREAM, 0);
  if(server_socket_fd < 0)
  {
    perror("Create Socket Failed:");
    exit(1);
  }
  int opt = 1;
  setsockopt(server_socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

  // 绑定socket和socket地址结构
  if(-1 == (bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr))))
  {
    perror("Server Bind Failed:");
    exit(1);
  }

  // socket监听
  if(-1 == (listen(server_socket_fd, LENGTH_OF_LISTEN_QUEUE)))
  {
    perror("Server Listen Failed:");
    exit(1);
  }

  while(1)
  {
    // 定义客户端的socket地址结构
    struct sockaddr_in client_addr;
    socklen_t client_addr_length = sizeof(client_addr);

    // 接受连接请求,返回一个新的socket(描述符),这个新socket用于同连接的客户端通信
    // accept函数会把连接到的客户端信息写到client_addr中
    int new_server_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_addr, &client_addr_length);
    if(new_server_socket_fd < 0)
    {
      perror("Server Accept Failed:");
      break;
    }

    // recv函数接收数据到缓冲区buffer中
    char buffer[BUFFER_SIZE];
    bzero(buffer, BUFFER_SIZE);
    if(recv(new_server_socket_fd, buffer, BUFFER_SIZE, 0) < 0)
    {
      perror("Server Recieve Data Failed:");
      break;
    }

    // 然后从buffer(缓冲区)拷贝到file_name中
    char file_name[FILE_NAME_MAX_SIZE+1];
    bzero(file_name, FILE_NAME_MAX_SIZE+1);
    strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer));
    printf("%s\n", file_name);

    // 打开文件并读取文件数据
    FILE *fp = fopen(file_name, "w");
    if(NULL == fp)
    {
      printf("File:%s Not Found\n", file_name);
    }
    else
    {
      bzero(buffer, BUFFER_SIZE);
      int length = 0;
      // 每读取一段数据,便将其发送给客户端,循环直到文件读完为止
      char*ch="bye";
while((length = recv(new_server_socket_fd, buffer, 1024, 0)) > 0)
  {
	if(strcmp(buffer,ch)==0)break;
    if(fwrite(buffer, sizeof(char), length, fp) < length)
    {
      printf("File:\t%s Write Failed\n", file_name);
      break;
    }
    bzero(buffer, BUFFER_SIZE);
  }fclose(fp);
int count=0;
    char s[21];
    FILE *fp1;
    if((fp1=fopen(file_name,"r"))==NULL){
        printf("Open the file failure...\n");
        exit(0);
    }
    while(fscanf(fp,"%s",s)!=EOF)
        count++;
    fclose(fp1);
itoa(count,buffer);
    printf("There is(are) %s word(s) in the text.\n",buffer);
      // 关闭文件

      send(new_server_socket_fd, buffer, strlen(buffer), 0);
      printf("File:%s Transfer Successful!\n", file_name);
    }
    // 关闭与客户端的连接
    close(new_server_socket_fd);
  }
  // 关闭监听用的socket
  close(server_socket_fd);
  return 0;
}

  • 实验截图

任务二:

使用多线程实现wc服务器并使用同步互斥机制保证计数正确<br>
上方提交代码<br>
下方提交测试<br>
对比单线程版本的性能,并分析原因
  • 多线程容易实现,关键在于互斥的计数,意思即为当某一个线程计数时,另一个线程就不能计数;
#include<netinet/in.h> // sockaddr_in
#include<sys/types.h>  // socket
#include<sys/socket.h> // socket
#include<stdio.h>    // printf
#include<stdlib.h>   // exit
#include<string.h>   // bzero
#include <pthread.h>
#include <semaphore.h>

#define SERVER_PORT 155213
#define LENGTH_OF_LISTEN_QUEUE 20
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512

int count_fd;
sem_t blank_number;
pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;

void * pthread_run(void*content)
{printf("%s","ahsf");
	int new_server_socket_fd=*((int *)content);
    char buffer[BUFFER_SIZE];
    bzero(buffer, BUFFER_SIZE);
    if(recv(new_server_socket_fd, buffer, BUFFER_SIZE, 0) < 0)
    {
      perror("Server Recieve Data Failed:");
    }

    // 然后从buffer(缓冲区)拷贝到file_name中
    char file_name[FILE_NAME_MAX_SIZE+1];
    bzero(file_name, FILE_NAME_MAX_SIZE+1);
    strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer));
    printf("%s\n", file_name);

    // 打开文件并读取文件数据
    FILE *fp = fopen(file_name, "w");
    if(NULL == fp)
    {
      //printf("File:%s Not Found\n", file_name);
    }
    else
    {
      bzero(buffer, BUFFER_SIZE);
      int length = 0;
      // 每读取一段数据,便将其发送给客户端,循环直到文件读完为止
      char*ch="bye";
while((length = recv(new_server_socket_fd, buffer, 1024, 0)) > 0)
  {
	if(strcmp(buffer,ch)==0)break;
    if(fwrite(buffer, sizeof(char), length, fp) < length)
    {
      //printf("File:\t%s Write Failed\n", file_name);
      break;
    }
    bzero(buffer, BUFFER_SIZE);
  }fclose(fp);
int count=0;
    char s[21];
    FILE *fp1;
    if((fp1=fopen(file_name,"r"))==NULL){
        printf("Open the file failure...\n");
        exit(0);
    }
    while(fscanf(fp,"%s",s)!=EOF)
        count++;
    fclose(fp1);
itoa(count,buffer);
    printf("There is(are) %s word(s) in the text.\n",buffer);
      // 关闭文件

      send(new_server_socket_fd, buffer, strlen(buffer), 0);
      printf("File:%s Transfer Successful!\n", file_name);
    }
    // 关闭与客户端的连接
    close(new_server_socket_fd);
	//sem_post( &blank_number );
	//pthread_mutex_lock( &counter_mutex );
	//count_fd--;
	//pthread_mutex_unlock(&counter_mutex);
}

void itoa(int i,char* string)
{
    int power,j;
    j=i;
    for(power=1;j>=10;j/=10)
        power*=10;
    for(;power>0;power/=10)
    {
        *string++='0'+i/power;
        i%=power;
    }
    *string='\0';
}

int main(void)
{
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
	int new_server_socket_fd;
	int server_socket_fd;
	pthread_t pid;
	count_fd=0;
	sem_init( &blank_number, 0, 5 );
  // 声明并初始化一个服务器端的socket地址结构
  
  bzero(&server_addr, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = htons(INADDR_ANY);
  server_addr.sin_port = htons(SERVER_PORT);

  // 创建socket,若成功,返回socket描述符
  server_socket_fd = socket(PF_INET, SOCK_STREAM, 0);
  if(server_socket_fd < 0)
  {
    perror("Create Socket Failed:");
    exit(1);
  }
  int opt = 1;
  setsockopt(server_socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

  // 绑定socket和socket地址结构
  if(-1 == (bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr))))
  {
    perror("Server Bind Failed:");
    exit(1);
  }

  // socket监听
  if(-1 == (listen(server_socket_fd, LENGTH_OF_LISTEN_QUEUE)))
  {
    perror("Server Listen Failed:");
    exit(1);
  }

  while(1)
  {
	//sem_wait( &blank_number );
    socklen_t client_addr_length = sizeof(client_addr);

    
    // accept函数会把连接到的客户端信息写到client_addr中
    new_server_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_addr, &client_addr_length);
    if(new_server_socket_fd < 0)
    {
      perror("Server Accept Failed:");
      break;
    }
printf("A new connection occurs!\n");
	//pthread_create( &pid ,NULL, &pthread_run, (void *)new_server_socket_fd );
	
  }
  // 关闭监听用的socket
  close(server_socket_fd);
  return 0;
}

  • 客户端和上一个任务一样

  • 运行截图

任务三

没能完成,计算机和arm机始终没有ping通;

实验体会

  • 这次实验体会最深的就是阻塞与非阻塞的理解,每到SOCKET recv时,系统就会中断等待对方的send,但如果此时对面没有send了,并且对面也是recv,那么整个系统就崩坏了,就永远停滞不前了,就像前面那个系统接收文件的循环
  • 服务器端
while((length = recv(new_server_socket_fd, buffer, 1024, 0)) > 0)
  {
	if(strcmp(buffer,ch)==0)break;
    if(fwrite(buffer, sizeof(char), length, fp) < length)
    {
      printf("File:\t%s Write Failed\n", file_name);
      break;
    }
    bzero(buffer, BUFFER_SIZE);
  }
  • 客户端
while((length = fread(buffer, sizeof(char), 1024, fp)) > 0)
      {
        if(send(client_socket_fd, buffer, length, 0) < 0)
        {
          printf("Send File:%s Failed./n", file_name);
          break;
        }
        bzero(buffer, BUFFER_SIZE);
      }
char ch[1024];
scanf("%s",ch);
send(client_socket_fd, "bye", 1024, 0);
	recv(client_socket_fd, buffer, 1024, 0);
  • 里面如果没有char ch[1024]; scanf("%s",ch); send(client_socket_fd, "bye", 1024, 0);三句,整个就会出现上面说的阻塞问题;
    而这里的解释就是scanf中断了传输,而采用bye字符串校验;
posted on 2017-11-19 16:00  20155213陆忠民  阅读(224)  评论(1编辑  收藏  举报