2017-2018-11 20155307刘浩 20155338常胜杰 20155335俞昆 实验三 实时系统实验报告

2017-2018-11 20155307刘浩 20155338常胜杰 20155335俞昆 实验三 实时系统

实验目的

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

实验步骤
1.实现wc功能
2.实现客户端给服务器传文件功能
3.在客户端调用wc函数统计传过来的文件的单词个数

要实现客户端和服务器的通信,这些我们在计算机网络中学过,具体为:客户端:socket()→bind()→connect()→send()→recv()→close(),然后服务器:socket()→bind()→accept()→recv()→send()→close()
为了正确实现统计单词个数的功能,找到其与wc命令的关系,先用「man 1 wc」查看wc命令的manpages,如下所示:

可见,wc命令的功能是统计指定文件中的字节数、字数、行数,
发现他的参数等信息如下:

实验代码如下:点击链接即可

或者这个是客户端,

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>  
#define PORT 155307 

#define MAXDATASIZE 100

int main(int argc, char *argv[])
{
    int sockfd, num;    
    char buf[MAXDATASIZE];   
    struct hostent *he;    
    struct sockaddr_in server;
    
    if (argc != 3)
    {
        printf("Usage: %s <IP Address><Filename>
",argv[0]);
        exit(1);
    }
    
    if((he=gethostbyname(argv[1]))==NULL)
    {
        printf("gethostbyname() error
");
        exit(1);
    }
    
    if((sockfd=socket(AF_INET,SOCK_STREAM, 0))==-1)
    {
        printf("socket() error
");
        exit(1);
    }
    bzero(&server,sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    server.sin_addr = *((struct in_addr *)he->h_addr);
    if(connect(sockfd, (struct sockaddr *)&server, sizeof(server))==-1)
    {
        printf("connect() error
");
        exit(1);
    }
char str[MAXDATASIZE] ;
strcpy(str,argv[2]);

if((num=send(sockfd,str,sizeof(str),0))==-1){
      printf("send() error
");
        exit(1);
    }
    if((num=recv(sockfd,buf,MAXDATASIZE,0))==-1)
    {
        printf("recv() error
");
        exit(1);
    }
    buf[num-1]='';
    printf("server message: %s
",buf);

    close(sockfd);
    return 0;
}

这个是服务器:

#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 155307

#define BACKLOG 1
#define MAXRECVLEN 1024

int main(int argc, char *argv[])
{
    char buf[MAXRECVLEN];
    int listenfd, connectfd;  
    struct sockaddr_in server; 
    struct sockaddr_in client; 
    socklen_t addrlen;

    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {

        perror("socket() error. Failed to initiate a socket");
        exit(1);
    }
 

    int opt = SO_REUSEADDR;
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    bzero(&server, sizeof(server));

    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    if(bind(listenfd, (struct sockaddr *)&server, sizeof(server)) == -1)
    {

        perror("Bind() error.");
        exit(1);
    }
    
    if(listen(listenfd, BACKLOG) == -1)
    {
        perror("listen() error. 
");
        exit(1);
    }

    addrlen = sizeof(client);
    while(1){
        if((connectfd=accept(listenfd,(struct sockaddr *)&client, &addrlen))==-1)
          {
            perror("accept() error. 
");
            exit(1);
          }
        FILE *stream;
        struct timeval tv;
        gettimeofday(&tv, NULL);
          printf("You got a connection from client's ip %s, port %d at time %ld.%ld
",inet_ntoa(client.sin_addr),htons(client.sin_port), tv.tv_sec,tv.tv_usec);
        
        int iret=-1;
        char d[1024];
         iret = recv(connectfd, buf, MAXRECVLEN, 0);
            if(iret>0)
            {
               strcpy(d,buf);
                stream = fopen(buf,"r");
                bzero(buf, sizeof(buf));
                strcat(buf,"单词数:");
                char s[21];
long int count = 0;
                while(fscanf(stream,"%s",s)!=EOF)
                count++;
                char str[10];
sprintf(str, "%ld", count); 
int n = sizeof(str);
str[n] = ''; 
strcat(buf,"
");
strcat(buf,str);
strcat(buf,"(");
strcat(buf,d);
strcat(buf,"单词数)");strcat(buf,"
");
                
            }else
            {
                close(connectfd);
                break;
            }

            send(connectfd, buf, iret, 0); 
        }
    
    close(listenfd);
    return 0;
}

最后的结果:

实验二:
使用多线程实现wc服务器并使用同步互斥机制保证计数正确

代码如下:

#include<stdlib.h> 
int main(int argc, char *argv[]) 
{ 
char ch; 
FILE *fp; 
long count=0; 
char s[21]; 
if(argc !=2) 
{ 
printf("文件名为:%s
",argv[0]); 
exit(EXIT_FAILURE); 
} 
exit(EXIT_FAILURE); 
} 
while(fscanf(fp,"%s",s)!=EOF) 
count++; 
fclose(fp); 
printf("File %s has %ld characters
",argv[1],count); 
return 0; 
}

或者可以去这里看一下

实验结果:

实验感想:此次实验在Linux下实现了wc命令统计文本文件中的单词数,在任务二中创建了一个并发服务器,节省了时间。可以使服务器同时为多个客户端服务了。

实验一完成的过程中还不是很困难,只是实验二中要注意下windows的socket转入linux时需要做的一系列改变。

原文地址:https://www.cnblogs.com/zhuanyedajiesanshinian/p/7857416.html