zoukankan      html  css  js  c++  java
  • 20155325 2017-2018 1 《信息安全系统设计基础》实验三

    实验要求

    实验一

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

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

    实验二

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

    实验过程

    实验一

    实现wc

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

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

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

    int MyWc(char buffer[],int length)
    {
        int i,j;
        int num=0;
        for(i=0;i<length;)
        {
           if( (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]=='^')   ||(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) 
    ",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("服务器文件无法被创建 
    ");  
                   exit(1);  
                 }
               while(length2 = recv(conn, buffer,BUFFER_SIZE, 0))  
               {  
                 if (length2 < 0)  
                 {  
                   printf("接受文件 %s 失败
    ",FileName);  
                   break;  
                 }      
               write_length = fwrite(buffer, sizeof(char), length2, fp); 
               printf("length2 = %d,write_length = %d
    ",length2,write_length);
               if (write_length < length2)  
                 {  
                   printf("服务器文件写入失败
    ");  
                   break;  
                 } 
                
               printf("
    ********************************************************
    ");
               
               sum = sum + MyWc(buffer,write_length);
               printf("
    sum = %d
    ",sum);
               bzero(buffer, BUFFER_SIZE); 
               length2 = 0;
               
            }  
            fclose(fp); 
            printf(" %s 成功接收
    ",FileName);   
            printf("****** sum = %d
    ",sum); 
    }
    

    客户端

    void Send(int sock_cli)
    {
       printf("进入传文件步骤。。。
     请输入文件名:");
       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!******
    ",FileName);  
            }  
       else
            {
                bzero(buffer, BUFFER_SIZE);  
                
                while( (length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)  
                {  
                    printf("length = %d
    ",length);  
      
                    // 发送buffer中的字符串到new_server_socket,实际上就是发送给客户端  
                    if (send(sock_cli, buffer, length, 0) < 0)  
                    {  
                        printf("%s 传送失败
    ", FileName);  
                        break;  
                    }  
      
                    bzero(buffer, BUFFER_SIZE);  
                }  
                fclose(fp);  
                printf("%s 传送成功
    ", 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.查错小技巧:在怀疑出错的代码段里放些输出,过滤掉很多无用的信息,获取到想要变量的值。在确定错误范围之后如果还是找不到错处,再结合单步调试查找。

  • 相关阅读:
    声明方法java实际开发中泛型使用需要注意的一些问题
    动态代理代理静态代理与动态代理
    方法返回在android手机开机后,在工程模式下的短信自注册开关默认开启
    打开关闭android如何默认打开小区广播?
    nullnullandroid Bound Services 绑定服务
    nullnullAndroid Interface Definition Language (AIDL) 接口描述语言
    nullnullContent Provider Basics 内容提供者的基本操作
    工程文件辉哥opencv学习之路【三】——opencv运行别人程序
    程序输入幸运数
    批处理相对路径51CTO自动领豆(Python)
  • 原文地址:https://www.cnblogs.com/GDDFZ/p/7862280.html
Copyright © 2011-2022 走看看