20155325 2017-2018 1 《信息安全系统设计基础》实验三

实验要求

实验一

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

上方提交代码
附件提交测试截图,至少要测试附件中的两个文件

实验二

使用多线程实现wc服务器并使用同步互斥机制保证计数正确
上方提交代码
下方提交测试
对比单线程版本的性能,并分析原因

实验过程

实验一

实现wc

本身在测试wc -w时发现它的字数统计得不对,我参照它的做法编写了第一个代码。

后来还是进行了修改,把我能想得到的判定单词数的情况都写到代码里。

我认为以下字符均是分割单词的:
' ' '\n' '\r' '\t' '.' '?' '!' ':' ',' '@' '&' '*' '~' '^' ';' ')' '“' '”' '('

int MyWc(char buffer[],int length)
{
    int i,j;
    int num=0;
    for(i=0;i<length;)
    {
       if( (buffer[i] == ' ')||(buffer[i]=='\n') ||(buffer[i]=='\r') ||(buffer[i]=='\t') ||(buffer[i]=='.')||(buffer[i]=='?')  ||(buffer[i]=='!') ||(buffer[i]==':')||(buffer[i]==',') ||(buffer[i]=='@') ||(buffer[i]=='&')||(buffer[i]=='*') ||(buffer[i]=='~')||(buffer[i]=='^')   ||(buffer[i]==';') ||(buffer[i]==')') ||(buffer[i]=='(') ||(buffer[i]=='"')  )
       {
          for(j = i+1;j<length;j++)
          {
             if( ((buffer[j]>='A')&&(buffer[j]<='Z')) || ((buffer[j]>='a')&&(buffer[j]<='z')) )
              {
        //        printf("(%d,%c),(%d %c) \n",i,buffer[i],j,buffer[j]);
                  num++;
                  i = j+1;
                  break;
              }
          }
       }
    i++;
    }
    return num;
}

实现大文件传输

以下是我特意修改了代码,更加清晰地显示了传输的过程。
当字符数过大时,则多传几次。

服务器

void Receive(int conn,char buffer[])
{
           int length2 = 0; 
           int write_length;
           int sum = 0;
           bzero(buffer, sizeof(buffer));  
           FILE *fp = fopen("b.txt", "w");  
           char FileName[15];
           memset(buffer,0,sizeof(FileName));
           recv(conn,FileName,15, 0);
           if (fp == NULL)  
             {  
               printf("服务器文件无法被创建 \n");  
               exit(1);  
             }
           while(length2 = recv(conn, buffer,BUFFER_SIZE, 0))  
           {  
             if (length2 < 0)  
             {  
               printf("接受文件 %s 失败\n",FileName);  
               break;  
             }      
           write_length = fwrite(buffer, sizeof(char), length2, fp); 
           printf("length2 = %d,write_length = %d\n",length2,write_length);
           if (write_length < length2)  
             {  
               printf("服务器文件写入失败\n");  
               break;  
             } 
            
           printf("\n********************************************************\n");
           
           sum = sum + MyWc(buffer,write_length);
           printf("\nsum = %d\n",sum);
           bzero(buffer, BUFFER_SIZE); 
           length2 = 0;
           
        }  
        fclose(fp); 
        printf(" %s 成功接收\n",FileName);   
        printf("****** sum = %d\n",sum); 
}

客户端

void Send(int sock_cli)
{
   printf("进入传文件步骤。。。\n 请输入文件名:");
   char FileName[15];
   char buffer[BUFFER_SIZE];
   int length = 0;  
   scanf("%s",FileName);
   send(sock_cli, FileName, sizeof(FileName),0); 
   FILE *fp = fopen(FileName,"r");
   if (fp == NULL)  
        {  
            printf("******%s Not Found!******\n",FileName);  
        }  
   else
        {
            bzero(buffer, BUFFER_SIZE);  
            
            while( (length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)  
            {  
                printf("length = %d\n",length);  
  
                // 发送buffer中的字符串到new_server_socket,实际上就是发送给客户端  
                if (send(sock_cli, buffer, length, 0) < 0)  
                {  
                    printf("%s 传送失败\n", FileName);  
                    break;  
                }  
  
                bzero(buffer, BUFFER_SIZE);  
            }  
            fclose(fp);  
            printf("%s 传送成功\n", FileName); 
            close(sock_cli); 
        }  
}

代码链接

代码

实验二

  • 连接时需要使用静态库libpthread.a,所以在线程函数在编译时,需要使用“-lpthread”链接库函数
  • int pthread_create(pthread_tt *thread,const pthread_attr_t *attr,void (start_routine)(void *),void *arg);
  • 在做这个时候我是拿上一个实验的代码改的,因为涉及编了一个函数,把一些东西传进了函数里,在同名其实不同意的情况下编译器不会报错,但是少考虑了一些就会导致程序出错,而且不好调试。在这种情况需要在编写的时候格外小心。

代码链接

代码

实验遇到的问题

  • 问题1:字数统计和wc -w 的不同。
  • 解决:我做了个小txt测试了一下wc -w ,结果是它本身测的就不对。

它是以空格,换行等为判定标准,所以我照着这个做了一个

后来……还是照着自己判定单词的标准做了程序。

  • 问题2:当文件较大无法全部传过去。

  • 解决:因为这个程序用单步调试不好调,我就在服务器里的一些步骤上加了几个输出。发现从第二组数据开始客户端就没把它传过去,后来发现是括号打错了使得第一次传输后就关闭了文件。

  • 问题3:在做多线程时报错:collect2:ld returned 1 exit status

  • 解决:emmm,编译的时候忘加“-lpthread”了

  • 问题4:传输文件名失败

  • 解决:直接从实验一代码改的

 Receive(conn,buffer);

原本是在主函数,直接就放进void *Pthread(void *conn)里了,应该修改为

Receive(sockid,buffer);

体会

1.出了bug不要慌,因为慌是没有作用的。

2.查错小技巧:在怀疑出错的代码段里放些输出,过滤掉很多无用的信息,获取到想要变量的值。在确定错误范围之后如果还是找不到错处,再结合单步调试查找。

posted @ 2017-11-19 21:44  难能可贵成功犯傻  阅读(178)  评论(0编辑  收藏  举报