1、2、打开一个虚拟终端,用gcc编译预先写好的服务器和客户端程序;3、运行服务器程序;4、打开另一个虚拟终端,运行客户端程序,连接成功后服务器给客户端发送数据;四、实验报告要求1 实验目的2 实验内容3 实验步骤记录自己实际完成的步骤,实验过程中所碰到的难题以及你解决问题的步骤和方法;4 实验技巧和心得体会附录:简单的客户/服务器通信示例一个建立分布式应用时最常用的范例便是客户机服务器模型。在这种方案中,客户应用程序向服务器程序请求服务,这种方式隐含了在建立客户机服务器间通信的非对称性。客户机服务器模型工作时要求有一套为客户机和服务器所共识的协议,以保证服务能够被提供或被接收,它必须在通信的两端
2、都被实现。在非对称协议中,一方为主机(服务器),另一方则是从机(客户机)。当服务被提供时必然存在“客户进程”和“服务进程”。一个服务器通常在一个众所周知的端口监听对服务的请求。也就是说,服务器一直处于休眠状态,直到一个客户对这个服务的端口提出连接请求。在这个时刻,服务程序被唤醒并且为客户提供服务,对客户的请求做出了适当的反应。其流程见图1。例1:服务器端程序通过一个连接向客户发送字符串n”。在PC机上运行服务器端程序,在开发板上运行客户端程序并输入服务器的IP地址,则开发板的LCD屏上能显示该字符串。服务器端发送程序host.c:#include stdlib.herrno.hstring.h
3、sys/types.hnetinet/in.hsys/wait.hsys/socket.hctype.h#define MYPORT 3000 /*定义服务器的监听端口*/#define Max 100 /*定义了服务器一次可以发送的字符数目*/#define BACKLOG 10 /*BACKLOG指定在请求队列中允许的最大请求数,进入的连接请求将在队列中等待accept()函数接受它们*/main( )int sock_fd,new_fd, numbytes,i; /*sock_fd,new_fd是套接字描述*/char bufMax; /*发送数据的缓冲区*/struct sockadd
4、r_in my_addr; /*服务器的地址结构体*/struct sockaddr_in their_addr; /*主机的地址结构体*/int sin_size;if(sock_fd=socket(AF_INET,SOCK_STREAM,0)= =1) /*建立流式套接字描述符*/ perror(socket); exit(1);/*服务器结构体的地址赋初值*/my_addr.sin_family=AF_INET;my_addr.sin_port=htons(MYPORT); /*服务器的端口号*/my_addr.sin_addr.s_addr=INADDR_ANY;bzero(&(my_
5、addr.sin_zero),8); /*填充0,凑齐长度*/if(bind(sock_fd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr)= = 1) /*绑定*/bindB /*绑定失败*/ exit(1);if(listen(sock_fd,BACKLOG)= =1) /*监听端口是否有请求*/listen /*监听失败*/exit(1); while(1)sin_size=sizeof(struct sockaddr_in); if (new_fd=accept(sock_fd,(struct sockaddr *)&their_a
6、ddr,&sin_size)= =1) perror(accept continue; printf(server:got connection from %sn,inet_ntoa(their_addr.sin_addr);if(!fork( ) /*子进程代码段:创建一个子进程,用来处理与刚建立的套接字的通信*/ if(send(new_fd,Hello,World! n,14,0)= = 1) /*发送字符串*/ perror(send close(new_fd); close(new_fd); /*父进程不再需要该socket*/ while(waitpid(1,NULL,WNOHAN
7、G)0); /*等待子进程结束,清除子进程所占用资源*/return 0;服务器首先创建一个socket,然后将该socket与本地地址/端口号捆绑,成功之后就在相应的socket上监听,当accpet捕捉到一个连接服务请求时,就生成一个新的socket,并调用fork( )函数产生一个子进程与客户机通信。该子进程处理数据传输部分,通过这个新的socket向客户端发送字符串n,然后关闭该socket。fork( )函数语句是一个单调用双返回的函数。若调用成功,在子进程中返回的值为0,在父进程中返回子进程的进程标识号;若调用失败,则返回1。包含fork函数的if语句是子进程代码部分,它与if语句
8、后面的父进程代码部分是并发执行的。客户端接收程序ethernet.c:unistd.h#include ./gui/gui.h /*用于LCD屏的显示*/#define PORT 3000 /*定义连接到服务器的端口号*/#define MAXDATASIZE 100 /*客户机一次可接收的最大传输量*/*延时程序,用于LCD屏的显示*/void delay( ) int i,j; for(i=0;i4500;i+) for(j=0;j4000;j+) /*将命令行输入的字符串IP地址转换成connect函数可识别的整数uiip*/int aiptoi(char * pszip,unsigne
9、d int* piip) char psziphere17,*psztmp1,*psztmp2,*pchar; /*定义指针*/ int i; bzero(psziphere,17); /*清空将要进行操作的数组*/ strcpy(psziphere,pszip); /*将要转换的IP地址存入该数组*/ strcat(psziphere,. /*在IP地址串的末尾加“”*/ for(i=0,psztmp1=psziphere,pchar=(char )piip;4;/*循环4次,将“”转变成0,并将字符串型转换成整型*/ if(psztmp2=strstr(psztmp1,)=NULL) /*
10、psztmp2返回指向字符“”位置的指针*/ return 0;psztmp20=0;(pchar+i)=atoi(psztmp1); /*调用atoi( )函数,将字符串转换成整数*/psztmp1=psztmp2+1; /*指针psatmp1移到下一段的开始*/ return 1;int main(int argc,char * argv) int sockfd,numbytes; unsigned int uiip; char bufMAXDATASIZE; struct sockaddr_in servaddr; if(!aiptoi(argv1,&uiip)|argc=1) /*检查
11、IP地址格式是否正确及IP是否输入*/the ip is not correct or have not input the ip! return 0;if (sockfd = socket(AF_INET,SOCK_STREAM,0)= =1) /*建立流式套接字描述符*/*给定主机信息*/servaddr.sin_family=AF_INET;servaddr.sin_port=htons(PORT);(servaddr.sin_zero),8);servaddr.sin_addr.s_addr=uiip;if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(struct sockaddr)=1) /*建立连接*/Cant connect to the server!initgraph( ); /*初始化显示环境*/if(numbytes=recv(sockfd,buf,MAXDATASIZE,0)= 1) /*接收服务器传送过来的字符串*/recvbufnumbytes=0;clearscreen( ); /*清屏*/textout(0,0,buf,0xffff,0x1111); /*显示字符串*/delay( );clearscreen(); close(sockfd);函数aiptoi()处理的
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1