2018-2019-1 20165226 实验三 并发程序

2018-2019-1 20165226 实验三 并发程序

目录



一、任务一
二、任务二
三、实验过程中遇到的问题及解决
四、实验感想

一、任务一



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

(二)实验步骤

  • 使用man wc查看wc(1)
  • wc命令
参数 用法
-c 统计字节数
-l 统计行数
-m 统计字符数,不能与 -c 连用
-w 统计字数,一个字被定义为由空白、跳格或换行字符分隔的字符串
-L 打印最长行的长度
-help 显示帮助信息
--version 显示版本信息
  • socket编程模型

(三)代码实现

  • 客户端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#pragma comment(lib,"ws2_32.lib")

#define MY_PORT 165226
#define DEST_IP "10.1.1.232"
int main()
{
    SOCKET con_socket;
    struct sockaddr_in remote_addr;
    char buffer[1024];
    char file_name[100];
    char readch;
    int i;

    WSADATA wsaDate;

    WSAStartup(MAKEWORD(1,1),&wsaDate);

    memset(file_name,0,sizeof(file_name));
    memset(buffer,0,sizeof(buffer));

    remote_addr.sin_family=AF_INET;
    remote_addr.sin_port=htons(MY_PORT);
    remote_addr.sin_addr.s_addr=inet_addr(DEST_IP);

    con_socket=socket(AF_INET,SOCK_STREAM,0);
    if(con_socket==-1)
    {
        printf("Client socket failed!");
        exit(0);
    }

    printf("Please Input File Name:\n");
    scanf("%s", file_name);

    if(connect(con_socket,(struct sockaddr*)&remote_addr,sizeof(struct sockaddr))==-1)
    {
        printf("Client connet failed!");
    }
    else
    {
        FILE *fp=fopen(file_name,"r");
        if(fp==NULL)
        {
            printf("%s File not Found!\n",file_name);
        }
        else
        {
            while((readch=fgetc(fp))!=EOF)
            {
                if(i<1024)
                {
                    buffer[i]=readch;
                    i++;
                }
                else
                {
                    i=0;
                    int n=send(con_socket, buffer, 1024, 0);
                    if(n==-1)
                    {
                        printf("Send File Error!\n");
                    }
                }
            }
            fclose(fp);
            printf("File:%s Transfer Finished!\n", file_name);
        }
        fclose(fp);
        long wordscount;
        recv(con_socket, &wordscount, sizeof(long), 0);
        printf("%ld\n", wordscount);
    }
    closesocket(con_socket);

    WSACleanup();
    return 0;
}
  • 服务端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#pragma comment(lib,"ws2_32.lib")
pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;

#define MY_PORT 165226

typedef struct socket_counter
{
    SOCKET send_socket;
    char buffer[1024];
}socket_counter;

void my_wc(socket_counter *my_counter);
int main()
{
    SOCKET listen_socket;//声明Socket接口变量
    struct sockaddr_in my_addr;//声明Socket地址变量
    int dummy,rev_length;
    //char buffer[1024];
    char file_name[100];
    pthread_t t;
    socket_counter *my_counter;

    WSADATA wsaDate;

    WSAStartup(MAKEWORD(1,1),&wsaDate);//启动版本

    listen_socket=socket(AF_INET,SOCK_STREAM,0);//声明为IPV4的TCP

    my_addr.sin_family=AF_INET;//IPV4
    my_addr.sin_port=htons(MY_PORT);//端口
    my_addr.sin_addr.s_addr=htonl(INADDR_ANY);//可以连接任一电脑

    dummy = sizeof(SOCKADDR);
    memset(file_name,0,sizeof(file_name));

    if( bind(listen_socket,(struct sockaddr*)&my_addr,sizeof(struct sockaddr))<0)//绑定本地IP与Socket
    {
       printf("Server Bind error!\n");
    }

    if(listen(listen_socket,5)<0)//等待序列,默认队列最多为5个请求
    {
        printf("Server Listen error!\n");
    }

    while(1)
    {
        my_counter->send_socket=accept(listen_socket,NULL,&dummy);//listen函数创建等待队列后,accept函数处理客户端发来的连接请求
        if(my_counter->send_socket==-1)
        {
            printf("Server Accept failed!\n");
            break;
        }
        printf("Accept success!\n");
        pthread_create(&t, NULL, &my_wc,my_counter);
        pthread_join(&t, NULL);
    }
    closesocket(listen_socket);//依次关闭连接
    WSACleanup();//清除
    return 0;
}
void my_wc(socket_counter *my_counter){
    pthread_mutex_lock( &counter_mutex );
    int len, i;
    long wordscount=0;
    int flag=1;
    while(1)
    {
        if((len=recv(my_counter->send_socket, my_counter->buffer, 1024, 0))>0)
        {
            for(i=0; i<len; i++)
            {
                if(flag==0)
                {
                    switch(my_counter->buffer[i])
                    {
                        case ' ':
                            wordscount++;
                            break;
                        case '\n':
                            wordscount++;
                            break;
                        case '\r':
                            wordscount++;
                            break;
                        default:
                            break;
                    }
                }
                if(my_counter->buffer[i]== ' ' || my_counter->buffer[i]=='\n' || my_counter->buffer[i]=='\r')
                    flag=1;
                else
                    flag=0;
            }
        }
        if(len<1024) break;
    }
    send(my_counter->send_socket, &wordscount, sizeof(long), 0);
    close(my_counter->send_socket);
    pthread_mutex_unlock( &counter_mutex );
}

(四)结果

  • 服务器端
  • 客户端

返回目录

二、任务二



(一)要求
使用多线程实现wc服务器并使用同步互斥机制保证计数正确
上方提交代码
下方提交测试

(二)实验步骤:
服务器代码需要增加两个功能

  • 增加多线程
  • 使用同步互斥

    只需更改服务器端代码

(三)代码实现

  • 服务器端
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#pragma comment(lib,"ws2_32.lib")
pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;

#define MY_PORT 165315

typedef struct socket_counter
{
    SOCKET send_socket;
    char buffer[1024];
}socket_counter;

void my_wc(socket_counter *my_counter);
int main()
{
    SOCKET listen_socket;//声明Socket接口变量
    struct sockaddr_in my_addr;//声明Socket地址变量
    int dummy,rev_length;
    //char buffer[1024];
    char file_name[100];
    pthread_t t;
    socket_counter *my_counter;

    WSADATA wsaDate;

    WSAStartup(MAKEWORD(1,1),&wsaDate);//启动版本

    listen_socket=socket(AF_INET,SOCK_STREAM,0);//声明为IPV4的TCP

    my_addr.sin_family=AF_INET;//IPV4
    my_addr.sin_port=htons(MY_PORT);//端口
    my_addr.sin_addr.s_addr=htonl(INADDR_ANY);//可以连接任一电脑

    dummy = sizeof(SOCKADDR);
    memset(file_name,0,sizeof(file_name));

    if( bind(listen_socket,(struct sockaddr*)&my_addr,sizeof(struct sockaddr))<0)//绑定本地IP与Socket
    {
       printf("Server Bind error!\n");
    }

    if(listen(listen_socket,5)<0)//等待序列,默认队列最多为5个请求
    {
        printf("Server Listen error!\n");
    }

    while(1)
    {
        my_counter->send_socket=accept(listen_socket,NULL,&dummy);//listen函数创建等待队列后,accept函数处理客户端发来的连接请求
        if(my_counter->send_socket==-1)
        {
            printf("Server Accept failed!\n");
            break;
        }
        printf("Accept success!\n");
        pthread_create(&t, NULL, &my_wc,my_counter);
        pthread_join(&t, NULL);
    }
    closesocket(listen_socket);//依次关闭连接
    WSACleanup();//清除
    return 0;
}
void my_wc(socket_counter *my_counter){
    pthread_mutex_lock( &counter_mutex );
    int len, i;
    long wordscount=0;
    int flag=1;
    while(1)
    {
        if((len=recv(my_counter->send_socket, my_counter->buffer, 1024, 0))>0)
        {
            for(i=0; i<len; i++)
            {
                if(flag==0)
                {
                    switch(my_counter->buffer[i])
                    {
                        case ' ':
                            wordscount++;
                            break;
                        case '\n':
                            wordscount++;
                            break;
                        case '\r':
                            wordscount++;
                            break;
                        default:
                            break;
                    }
                }
                if(my_counter->buffer[i]== ' ' || my_counter->buffer[i]=='\n' || my_counter->buffer[i]=='\r')
                    flag=1;
                else
                    flag=0;
            }
        }
        if(len<1024) break;
    }
    send(my_counter->send_socket, &wordscount, sizeof(long), 0);
    close(my_counter->send_socket);
    pthread_mutex_unlock( &counter_mutex );

(四)运行结果

(五)实验分析
相比单线程,多线程运行时可以同时多个客户端一起给服务器传文件效率更高

返回目录

三、实验过程中遇到的问题及解决


  • 问题1:Fatal error: stdafx.h : No such file or directory
  • 问题1解决方案:建工程自带,将其删除即可;或者是手动添加头文件
  • 问题 2:
||=== 生成: Debug in ccc (compiler: GNU GCC Compiler) ===|
obj\Debug\main.o||In function `[email protected]':|
D:\code\ccc\main.cpp|16|undefined reference to `[email protected]'|
obj\Debug\main.o||In function `main':|
D:\code\ccc\main.cpp|28|undefined reference to `[email protected]'|
D:\code\ccc\main.cpp|30|undefined reference to `[email protected]'|
D:\code\ccc\main.cpp|33|undefined reference to `[email protected]'|
D:\code\ccc\main.cpp|40|undefined reference to `[email protected]'|
D:\code\ccc\main.cpp|41|undefined reference to `[email protected]'|
D:\code\ccc\main.cpp|43|undefined reference to `[email protected]'|
D:\code\ccc\main.cpp|49|undefined reference to `[email protected]'|
D:\code\ccc\main.cpp|56|undefined reference to `[email protected]'|
D:\code\ccc\main.cpp|62|undefined reference to `[email protected]'|
D:\code\ccc\main.cpp|62|undefined reference to `[email protected]'|
||=== Build 失败了: 11 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===
  • 问题2解决方案:手动添加“libws2_32.a”到链接器中。
  • 问题3:出现error C4996:’fopen’问题
  • 问题3解决方案:编辑预处理器(添加“_CRT_SECURE_NO_WAR NINGS”)

返回目录

四、实验感想


  • 本次实验学习了如何使用wc指令,同时分别采用单线程和多线程来实现服务器和客户端之间的信息传输。
  • 对TCP通信过程有了更深的理解,并熟练掌握了Socket编程,同时复习了C语言编程,复习了读取文件、多线程、互斥等知识点。

返回目录

原文地址:https://www.cnblogs.com/musea/p/9976409.html

时间: 2024-07-31 04:44:38

2018-2019-1 20165226 实验三 并发程序的相关文章

实验三 并发程序

实验三 并发程序 1.学习使用Linux命令wc(1) 要求: 1.基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 2.客户端传一个文本文件给服务器 3.服务器返加文本文件中的单词数 实验过程 首先是用man wc命令学习wc的用法 wc命令参数: (1)-c:统计字节数. (2)-l:统计行数. (3)-m:统计字符数.这个标志不能与 -c 标志一起使用. (4)-w:统计字数.一个字被定义为由空白.跳格或换行字符分隔的字符串. (5)-L:打印最长

2017-2018-1 20155214 《信息安全系统设计基础》实验三 并发程序

2017-2018-1 20155214 <信息安全系统设计基础> 实验三 并发程序 实验要求 任务一 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文本文件给服务器 服务器返加文本文件中的单词数 任务二 使用多线程实现wc服务器并使用同步互斥机制保证计数正确 上方提交代码 下方提交测试 对比单线程版本的性能,并分析原因 任务三 交叉编译多线程版本服务器并部署到实验箱中 PC机作客户端测试wc服务器 实

20165310 实验三-并发程序

20165310 实验三-并发程序 任务一:学习使用Linux命令wc(1) wc(1) 命令的作用:统计指定文件中的字节数.字数.行数,并将统计结果显示输出.该命令统计指定文件中的字节数.字数.行数.如果没有给出文件名,则从标准输入读取.wc同时也给出所指定文件的总统计数. man方法查询结果: 利用wc命令统计文档text1.txt和text2.txt的字数,并且作为接下来实验正确性的判断标准 任务二:基于Linux Socket程序设计实现wc(1)服务器和客户端 实验要求 客户端传一个文

2018-2019-1 20165212 实验三-并发程序设计

2018-2019_20165212_20165222_20165313<信息安全系统设计基础>实验三报告 任务一 C语言模拟wc命令.实现linux下客户端服务器文件通信 使用man wc命令查看wc命令的基本用法: 可知wc命令的功能为:统计指定文件中的字节数.字数.行数等,并将统计结果显示输出.常用的参数为: -c:统计字节数 -l:统计行数 -m:统计字符数,且不能与-c参数一起使用 -w:统计字数,一个字被定义为由空白.跳格或换行字符分割的字符串 -L:打印最长行的长 但是,如果我们

20165226 实验三 敏捷开发与XP实践

实验三 敏捷开发与XP实践 实验目的 一.安装alibaba 插件,解决代码中的规范问题.在IDEA中使用工具(Code->Reformate Code)格式化代码,研究一下Code菜单,比较功能. 二.在码云上把自己的学习搭档加入自己的项目中,下载搭档实验二的Complex代码,加入不少于三个JUnit单元测试用例,测试并上传代码至码云 三.下载搭档的代码,完成重构内容的练习. 四.结合重构,git,代码标准,以结对的方式完成Java密码学相关内容的学习. 实验内容及步骤 (一)安装aliba

2018-2019-1 20165231 实验三 实时系统

实验报告封面 课程:信息安全系统设计基础 班级:1652班 姓名:王杨鸿永 学号:20165231 指导教师:娄嘉鹏 实验日期:2018年11月14日 实验时间:15:25 - 17:50 实验序号:实验三 实验名称:实时系统 实验内容 实验三-并发程序-1 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文本文件给服务器 服务器返加文本文件中的单词数 wc命令参数 -c 统计字节数. l统计行数. m 统

2017-2018-1 20155229 实验三 实时系统

2017-2018-1 20155229 实验三 实时系统 实验目的 了解实时系统的信息.特点等内容. 学习客户端和服务器之间的工作原理,并编写代码实现. 实验步骤 实验三-并发程序-1 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文本文件给服务器 服务器返加文本文件中的单词数 wc命令的功能: 统计指定文件中的字节数.字数.行数,并将统计结果显示输出.该命令统计指定文件中的字节数.字数.行数.如果没有

2017-2018-1 20155227 实验三 实时系统

2017-2018-1 20155227 实验三 实时系统 实验目的,实验步骤 实验过程如下. 实验三-并发程序-1 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文本文件给服务器 服务器返加文本文件中的单词数 上方提交代码 附件提交测试截图,至少要测试附件中的两个文件 client.c: #include<netinet/in.h> // sockaddr_in #include<sys/typ

2017-2018-1 20155234 实验三 实时系统及mypwd实现

2017-2018-1 20155234实验三实时系统及mypwd实现 实验三-并发程序-1 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文本文件给服务器 服务器返加文本文件中的单词数 使用man命令查看wc的用法 自己实现的wc截图: 实验三-并发程序-2 使用多线程实现wc服务器并使用同步互斥机制保证计数正确 对比单线程版本的性能,并分析原因 截图: mypwd实现 使用man命令查看wc的用法 m