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

1.学习使用Linux命令wc

基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端
客户端传一个文本文件给服务器
服务器返加文本文件中的单词数
上方提交代码
附件提交测试截图,至少要测试附件中的两个文件

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

上方提交代码
下方提交测试
对比单线程版本的性能,并分析原因

linux socket编程常用函数

  • socket()
    我们使用系统调用socket()来获得文件描述符:
    #include<sys/types.h> #include<sys/socket.h> int socket(int domain,int type,int protocol);
    第一个参数domain设置为“AF_INET”。
    第二个参数是套接口的类型:SOCK_STREAM或
    SOCK_DGRAM。第三个参数设置为0。
    系统调用socket()只返回一个套接口描述符,如果出错,则返回-1。

  • bind()
    一旦你有了一个套接口以后,下一步就是把套接口绑定到本地计算机的某一个端口上。但如果你只想使用connect()则无此必要。
    下面是系统调用bind()的使用方法:
    #include<sys/types.h> #include<sys/socket.h> intbind(int sockfd,struct sockaddr*my_addr,int addrlen);
    第一个参数sockfd是由socket()调用返回的套接口文件描述符。
    第二个参数my_addr是指向数据结构sockaddr的指针。数据结构sockaddr中包括了关于你的地址、端口和IP地址的信息。
    第三个参数addrlen可以设置成sizeof(structsockaddr)。
    下面是一个例子:
    #include<string.h> #include<sys/types.h> #include<sys/socket.h> #define MYPORT 3490 main() { int sockfd; struct sockaddr_inmy_addr; sockfd=socket(AF_INET,SOCK_STREAM,0); my_addr.sin_family=AF_INET; my_addr.sin_port=htons(MYPORT); my_addr.sin_addr.s_addr=inet_addr("132.241.5.10"); bzero(&(my_addr.sin_zero),8); bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr));
    如果出错,bind()也返回-1。
    如果你使用connect()系统调用,那么你不必知道你使用的端口号。当你调用connect()时,它检查套接口是否已经绑定,如果没有,它将会分配一个空闲的端口。

  • connect()
    系统调用connect()的用法如下:
    #include<sys/types.h> #include<sys/socket.h> int connect(int sockfd,struct sockaddr* serv_addr,int addrlen);
    第一个参数还是套接口文件描述符,它是由系统调用socket()返回的。
    第二个参数是serv_addr是指向数据结构sockaddr的指针,其中包括目的端口和IP地址。
    第三个参数可以使用sizeof(structsockaddr)而获得。
    下面是一个例子:
    #include<string.h> #include<sys/types.h> #include<sys/socket.h> #define DEST_IP "132.241.5.10" #define DEST_PORT 23 main() { intsockfd; structsockaddr_indest_addr; sockfd=socket(AF_INET,SOCK_STREAM,0); dest_addr.sin_family=AF_INET; dest_addr.sin_port=htons(DEST_PORT); dest_addr.sin_addr.s_addr=inet_addr(DEST_IP); bzero(&(dest_addr.sin_zero),8); connect(sockfd,(structsockaddr*)&dest_addr,sizeof(struct sockaddr));

    同样,如果出错,connect()将会返回-1。

  • listen()
    如果你希望不连接到远程的主机,也就是说你希望等待一个进入的连接请求,然后再处理它们。这样,你通过首先调用listen(),然后再调用accept()来实现。
    系统调用listen()的形式如下:
    intl isten(int sockfd,int backlog);
    第一个参数是系统调用socket()返回的套接口文件描述符。
    第二个参数是进入队列中允许的连接的个数。进入的连接请求在使用系统调用accept()应答之前要在进入队列中等待。这个值是队列中最多可以拥有的请求的个数。大多数系统的缺省设置为20。你可以设置为5或者10。当出错时,listen()将会返回-1值。
    当然,在使用系统调用listen()之前,我们需要调用bind()绑定到需要的端口,否则系统内核将会让我们监听一个随机的端口。所以,如果你希望监听一个端口,下面是应该使用的系统调用的顺序:
    socket();
    bind();
    listen();

  • accept()
    系统调用accept()比较起来有点复杂。在远程的主机可能试图使用connect()连接你使用
    listen()正在监听的端口。但此连接将会在队列中等待,直到使用accept()处理它。调用accept()
    之后,将会返回一个全新的套接口文件描述符来处理这个单个的连接。这样,对于同一个连接
    来说,你就有了两个文件描述符。原先的一个文件描述符正在监听你指定的端口,新的文件描
    述符可以用来调用send()和recv()。
    调用的例子如下:
    #include<sys/socket.h> intaccept(intsockfd,void*addr,int*addrlen);
    第一个参数是正在监听端口的套接口文件描述符。第二个参数addr是指向本地的数据结构
    sockaddr_in的指针。调用connect()中的信息将存储在这里。通过它你可以了解哪个主机在哪个
    端口呼叫你。第三个参数同样可以使用sizeof(structsockaddr_in)来获得。
    如果出错,accept()也将返回-1。下面是一个简单的例子:
    ```
    #include<string.h>
    #include<sys/types.h>
    #include<sys/socket.h>
    #define MYPORT 3490
    #define BACKLOG 10
    main()
    {
    intsockfd,new_fd;
    structsockaddr_inmy_addr;
    structsockaddr_intheir_addr;
    intsin_size;
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    my_addr.sin_family=AF_INET;
    my_addr.sin_port=htons(MYPORT);
    my_addr.sin_addr.s_addr=INADDR_ANY;
    bzero(&(my_addr.sin_zero),8);

    bind(sockfd,(structsockaddr*)&my_addr,sizeof(structsockaddr));
    listen(sockfd,BACKLOG);
    sin_size=sizeof(structsockaddr_in);
    new_fd=accept(sockfd,&their_addr,&sin_size);
    ```

    下面,我们将可以使用新创建的套接口文件描述符new_fd来调用send()和recv()。

  • send() 和recv()
    系统调用send()的用法如下:
    int send(int sockfd,const void* msg,int len,int flags);
    第一个参数是你希望给发送数据的套接口文件描述符。它可以是你通过socket()系统调用返回的,也可以是通过accept()系统调用得到的。
    第二个参数是指向你希望发送的数据的指针。
    第三个参数是数据的字节长度。第四个参数标志设置为0。
    下面是一个简单的例子:
    char*msg="Beejwashere!"; intlen,bytes_sent; .. len=strlen(msg); bytes_sent=send(sockfd,msg,len,0); ...
    系统调用send()返回实际发送的字节数,这可能比你实际想要发送的字节数少。如果返回的字节数比要发送的字节数少,你在以后必须发送剩下的数据。当send()出错时,将返回-1。
    系统调用recv()的使用方法和send()类似:
    int recv(int sockfd,void* buf,int len,unsigned int flags);
    第一个参数是要读取的套接口文件描述符。
    第二个参数是保存读入信息的地址。
    第三个参数是缓冲区的最大长度。第四个参数设置为0。
    系统调用recv()返回实际读取到缓冲区的字节数,如果出错则返回-1。
    这样使用上面的系统调用,你可以通过数据流套接口来发送和接受信息。

  • sendto() 和recvfrom()
    因为数据报套接口并不连接到远程的主机上,所以在发送数据包之前,我们必须首先给出目的地址,请看:
    int sendto(int sockfd,const void* msg,int len,unsigned int flags,conststruct sockaddr*to,inttolen);
    除了两个参数以外,其他的参数和系统调用send()时相同。
    参数to是指向包含目的IP地址和端口号的数据结构sockaddr的指针。
    参数tolen可以设置为sizeof(structsockaddr)。
    系统调用sendto()返回实际发送的字节数,如果出错则返回-1。
    系统调用recvfrom()的使用方法也和recv()的十分近似:
    int recvfrom(int sockfd,void* buf,int len,unsigned int flagsstruct sockaddr* from,int* fromlen);
    参数from是指向本地计算机中包含源IP地址和端口号的数据结构sockaddr的指针。
    参数fromlen设置为sizeof(struct sockaddr)。
    系统调用recvfrom()返回接收到的字节数,如果出错则返回-1。

  • close() 和shutdown()
    你可以使用close()调用关闭连接的套接口文件描述符:
    close(sockfd);
    这样就不能再对此套接口做任何的读写操作了。
    使用系统调用shutdown(),可有更多的控制权。它允许你在某一个方向切断通信,或者切断双方的通信:
    int shutdown(int sockfd,int how);
    第一个参数是你希望切断通信的套接口文件描述符。第二个参数how值如下:
    0—Furtherreceivesaredisallowed
    1—Furthersendsaredisallowed
    2—Furthersendsandreceivesaredisallowed(likeclose())
    shutdown()如果成功则返回0,如果失败则返回-1。

服务器:

#include "time.h"
#include<stdlib.h>
#include<pthread.h>
#include<sys/socket.h>
#include<sys/types.h>       //pthread_t , pthread_attr_t and so on.
#include<stdio.h>
#include<netinet/in.h>      //structure sockaddr_in
#include<arpa/inet.h>       //Func : htonl; htons; ntohl; ntohs
#include<assert.h>          //Func :assert
#include<string.h>          //Func :memset
#include<unistd.h>          //Func :close,write,read
#define SOCK_PORT 13222
#define BUFFER_LENGTH 1024
#define MAX_CONN_LIMIT 512     //MAX connection limit
struct sockaddr_in s_addr_client;
itoa(int n,char str[64]);
static void Data_handle(void * sock_fd);   //Only can be seen in the file
int main()
{int sockfd_server;int sockfd;int fd_temp;struct sockaddr_in s_addr_in;   int client_length;sockfd_server = socket(AF_INET,SOCK_STREAM,0);  //ipv4,TCPassert(sockfd_server != -1);//before bind(), set the attr of structure sockaddr.memset(&s_addr_in,0,sizeof(s_addr_in));s_addr_in.sin_family = AF_INET;s_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);  //trans addr from uint32_t host byte order to network byte order.s_addr_in.sin_port = htons(SOCK_PORT);          //trans port from uint16_t host byte order to network byte order.fd_temp = bind(sockfd_server,(struct sockaddr *)(&s_addr_in),sizeof(s_addr_in));if(fd_temp == -1){fprintf(stderr,"bind error!\n");exit(1);}fd_temp = listen(sockfd_server,MAX_CONN_LIMIT);if(fd_temp == -1){fprintf(stderr,"listen error!\n");exit(1);}while(1){printf("waiting for new connection...\n");pthread_t thread_id;client_length = sizeof(s_addr_client);//Block here. Until server accpets a new connection.sockfd = accept(sockfd_server,(struct sockaddr *)(&s_addr_client),(socklen_t *)(&client_length));if(sockfd == -1){fprintf(stderr,"Accept error!\n");continue;                               //ignore current socket ,continue while loop.}printf("A new connection occurs!\n");pthread_create(&thread_id,NULL,(void *)(&Data_handle),(void *)(&sockfd));pthread_join(thread_id,NULL);}//Clearint ret = shutdown(sockfd_server,SHUT_WR); //shut down the all or part of a full-duplex connection.assert(ret != -1);printf("Server shuts down\n");return 0;
}static void Data_handle(void * sock_fd)
{int fd = *((int *)sock_fd);int i_recvBytes;int i,count=0;char buffer[1024];char data_send[64]="hello";//char * data_send = "Server has received your request!\n";//strcat(data_send,inet_ntoa(s_addr_client.sin_addr));
//  puts(s_addr_client.sin_addr)//strcat(data_send,"\n20155222\n");while(1){printf("waiting for request...\n");//Reset data.//memset(data_recv,0,BUFFER_LENGTH);// write(fd,data_send,strlen(data_send));while((i_recvBytes = read(fd,buffer,1024))>0){//count=0;int flag = 0;//  printf("%d\n",i_recvBytes);//  printf("%s\n",buffer);for(i=0;i<i_recvBytes;i++){if(flag==0){switch(buffer[i]){case ' ':count++;break;case '\n':count++;break;case '\r':count++;break;}}if(buffer[i]==' '||buffer[i]=='\n'||buffer[i]=='\r')flag=1;else flag=0;}/*for(i=0;i<i_recvBytes;i++)if((buffer[i]==' '||buffer[i]==10)&&((buffer[i-1]>='A'&&buffer[i-1]<='Z')||(buffer[i-1]>='a'&&buffer[i-1]<='z'))){count++;break;}i--;for(;i<i_recvBytes;i++)if((buffer[i]==' '||buffer[i]=='('||buffer[i]=='\t'||buffer[i]=='\r')&&((buffer[i+1]>='A'&&buffer[i+1]<='Z')||(buffer[i+1]>='a'&&buffer[i+1]<='z')))*///for(i=0;i<i_recvBytes;i++)//if(buffer[i]==' '||buffer[i]=='\n'||buffer[i]=='\t')//  count++;bzero(buffer,1024);//printf("%d\n",count);}//printf("fffaff\n");write(fd,data_send,strlen(data_send));/*while((i_recvBytes = read(fd,buffer,1024))>0){//  puts(buffer);for(i=0;i<i_recvBytes;i++)if(buffer[i]!=' '&&buffer[i]!='\n')count++;}printf("a");*//*if(i_recvBytes == 0){printf("Maybe the client has closed\n");break;}if(i_recvBytes == -1){fprintf(stderr,"read error!\n");break;}if(strcmp(data_recv,"quit")==0){printf("Quit command!\n");break;                           //Break the while loop.}*/// printf("read from client : %s\n",data_recv);//printf("%d",count);bzero(data_send,64);itoa(count,data_send);puts(data_send);if(write(fd,data_send,strlen(data_send)+1) == -1){printf("send failure"); break;}time_t timep;time (&timep);break;/*if(write(fd,ctime(&timep),strlen(ctime(&timep))) == -1){break;}*/}//Clearprintf("terminating current client_connection...\n");close(fd);            //close a file descriptor.pthread_exit(NULL);   //terminate calling thread!
}
itoa(int n,char str[64])
{int i=0,len;char temp;while(n>10){str[i]=n%10+48;//            printf("%d,%c\n",n,str[i]);n/=10;i++;}str[i]=n+48;len=strlen(str);for(i=0;i<len/2;i++){temp=str[i];str[i]=str[len-i-1];str[len-i-1]=temp;}
}

客户端:

#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h>       //pthread_t , pthread_attr_t and so on.
#include<stdio.h>
#include<netinet/in.h>      //structure sockaddr_in
#include<arpa/inet.h>       //Func : htonl; htons; ntohl; ntohs
#include<assert.h>          //Func :assert
#include<string.h>          //Func :memset
#include<unistd.h>          //Func :close,write,read
#define SOCK_PORT 13225
#define BUFFER_LENGTH 1024
int main()
{int sockfd;int tempfd;FILE *fp=NULL;struct sockaddr_in s_addr_in;char data_send[BUFFER_LENGTH]="aa";char data_recv[BUFFER_LENGTH];memset(data_send,0,BUFFER_LENGTH);memset(data_recv,0,BUFFER_LENGTH);sockfd = socket(AF_INET,SOCK_STREAM,0);       //ipv4,TCPif(sockfd == -1){fprintf(stderr,"socket error!\n");exit(1);}//before func connect, set the attr of structure sockaddr.memset(&s_addr_in,0,sizeof(s_addr_in));s_addr_in.sin_addr.s_addr = inet_addr("127.0.0.1");      //trans char * to in_addr_ts_addr_in.sin_family = AF_INET;s_addr_in.sin_port = htons(SOCK_PORT);tempfd = connect(sockfd,(struct sockaddr *)(&s_addr_in),sizeof(s_addr_in));if(tempfd == -1){fprintf(stderr,"Connect error! \n");exit(1);}while(1){if((fp=fopen("test2.txt","r"))==NULL){printf("file no found");break;}char buffer[1024]="";printf("Please input something you wanna say(input \"quit\" to quit):\n");//scanf("%s",&data_send);int ret;     //scanf("%[^\n]",data_send);         //or you can also use thisfseek(fp,0,SEEK_END);int len = ftell(fp);rewind(fp);//printf("%ld\n",len);while(1){
//  len-=1024;
//printf("%d\n",len);if(len<=0)break;ret=fgets(buffer,1024,fp);
//  printf("%d\n",ret);
//      printf("%s",buffer);
//      printf("bbb\n");tempfd = write(sockfd,buffer,strlen(buffer));
//      printf("%d\n",tempfd);if(tempfd<=0){printf("error\n");break;}len-=strlen(buffer);bzero(buffer,1024);}//fread(buffer,1,len,fp);//write(sockfd,buffer,strlen(buffer));printf("finish send\n");if(shutdown(sockfd,1)==1)printf("shutdown writting");if(strcmp(data_send,"quit") == 0)  //quit,write the quit request and shutdown client{break;}elsewhile(1){tempfd = read(sockfd,data_recv,BUFFER_LENGTH);if(tempfd<=0)exit(0);//assert(tempfd != -1);printf("%s\n",data_recv);memset(data_send,0,BUFFER_LENGTH);memset(data_recv,0,BUFFER_LENGTH);}}int ret = shutdown(sockfd,SHUT_WR);       //or you can use func close()--<unistd.h> to close the fdassert(ret != -1);return 0;
}

转载于:https://www.cnblogs.com/20155222lzj/p/7859850.html

2017-2018-1 20155222实验三 实时系统相关推荐

  1. 2018-2019-1 20165305 实验三 实时系统

    实验三 实时系统 码云链接 实验三-并发程序-1 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文本文件给服 ...

  2. 20145208 20145230 20145235 《信息安全系统设计基础》实验三 实时系统的移植

    20145208 20145230 20145235 <信息安全系统设计基础>实验三 实时系统的移植 转载于:https://www.cnblogs.com/20145235litao/p ...

  3. 2017-2018-1 20155209 实验三 实时系统

    2017-2018-1 20155209 实验三 实时系统 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文 ...

  4. 2018-2019-1 20165315 实验三 实时系统

    2018-2019-1 20165315 实验三 实时系统 任务一 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端,客户端 ...

  5. 2017-2018-1 20155223 实验三 实时系统

    2017-2018-1 20155223 实验三 实时系统 实验1 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端 ...

  6. 2018-2019-1 20165219 实验三 实时系统

    2018-2019-1 20165219 实验三 实时系统 任务一 实验要求 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户 ...

  7. 2017-2018-1 20155320 实验三——实时系统

    2017-2018-1 20155320 实验三--实时系统 实验三-并发程序-1 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的> ...

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

    2017-2018-11 20155307刘浩 20155338常胜杰 20155335俞昆 实验三 实时系统 实验目的 实验一: 学习使用Linux命令wc(1) 基于Linux Socket程序设 ...

  9. 2017-2018-1 20155332实验三 实时系统报告

    20155332 实验三 任务一: 1.学习使用Linux命令wc(1)2.基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端3.客户端传一个文本文件给服务器4 ...

最新文章

  1. EdgeGallery — MEP — 安装部署
  2. Springboot使用JPA框架对数据库实现增删改查(附详细代码)
  3. ubuntu 20.04 设置网关_如何把Ubuntu升级到Ubuntu 20.04 LTS 最新版本
  4. Mybatis Plus——[Could not set property 'id' of '***' with value]解决方案
  5. python六角形的绘制
  6. 干旱对数据中心的影响
  7. java 通过id获取html代码_Maven私服安装配置,java通过私服下载代码,并打包后上传到私服(Nexus)...
  8. Python数据清理之数据质量
  9. 在CentOS 7 上搭建LAMP
  10. 10月15日发布!谷歌Pixel 4系列或将全系支持5G
  11. java收银台打印小票_智慧收银台—小票打印机接入方式
  12. python程序画漂亮图_用python画图代码:正弦图像、多轴图等案例
  13. 微软商店下载的python_微软商店可下载安装Python 3.7啦
  14. 区块链十年一梦:有人辞官归故里,有人星夜来赶考
  15. Linux/Ubuntu18.04安装RTL8811cu驱动
  16. 简单描述进程 vs 线程
  17. nb移动udp_【一点资讯】华为L3 | 集采补考真题及答案 www.yidianzixun.com
  18. 辰视智能携手大族机器人亮相深圳工业展暨22届SIMM深圳机械展
  19. 高德地图-实现地图搜索点选位置功能
  20. ArcGIS Pro 简明教程(1)Pro简介

热门文章

  1. 【多标签文本分类】Large Scale Multi-label Text Classification with Semantic Word Vectors
  2. 【keras】Input 0 of layer conv2d is incompatible with the layer. expected ndim=4, found ndim=3
  3. LeetCode 547. Friend Circles--Python解法--笔试算法题
  4. PAT甲级真题 1018 A+B in Hogwarts--python解法
  5. 打造自己的树莓派监控系统2--内存监控-matplotlib显示数据
  6. python自动整理文件夹_计算机文件和文件夹的Python自动管理,自动化,电脑,及
  7. 面试不怂之redis与缓存大全
  8. sharding-jdbc分库分表的 4种分片策略
  9. Springboot swagger2教程
  10. [SpringBoot之Druid]