一、什么是client/server模型
client/server翻译过来是客户端/服务器的意思,该模型最基础的表现方式是客户端连接上服务器后向服务器发送相应请求由服务器处理完成后做出相应动作。通过它可以充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销。
二、client/server模型服务器端实现的一个简单例子
1)、服务器端的编程大致可以总结为以下流程:
1、创建套接字(服务器端用于监听,相当于上一篇总结中的大老板)
2、设置IP和端口,并绑定端口(给大老板分配办公室)
3、将套接字转化为监听套接字(老板坐在窗边边喝茶边等待员工来办事)
4、接收连接(员工来办事了,为员工分配一个助手或者让管这事的小老板出来解决问题,自己依然等待下一个员工到来)
5、处理事件(员工和小老板商量解决问题)
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
int main(void)
{
int sev_fd,cli_fd,cli_addr_len;
struct sockaddr_in sev_addr,cli_addr;
char buf[1048576];
int count;
memset(buf,0,sizeof(buf));
memset(&cli_addr,0,sizeof(cli_addr));
//初始化套接字和设置IP
sev_fd = socket(AF_INET,SOCK_STREAM,0); //这就是我们的大老板
if (sev_fd == -1)
{
perror("Socket Error"); return EXIT_FAILURE;
}
sev_addr.sin_family = AF_INET;
sev_addr.sin_port = htons(8080);
sev_addr.sin_addr.s_addr = htonl(INADDR_ANY);
//绑定端口
if (bind(sev_fd, (struct sockaddr *)&sev_addr, sizeof(struct sockaddr_in)) == -1) //给老板分配办公室
{
perror("Bind Error"); return EXIT_FAILURE;
}
//服务器端监听
if (listen(sev_fd,20)) //老板坐在窗边等待员工来访
{
perror("Listen Error"); return EXIT_FAILURE;
}
//服务器端接受连接
cli_addr_len = sizeof(struct sockaddr_in);
cli_fd = accept(sev_fd, (struct sockaddr *)&cli_addr, &cli_addr_len); //员工来访后大老板分配一个小老板和员工解决问题
if (cli_fd == -1)
{
perror("Accept Error"); return EXIT_FAILURE;
}
while(1)
{
//服务器端接收数据
if ((count = recv(cli_fd, buf, sizeof(buf), 0)) == -1) //小老板和圆通通话(这里是听)
{
perror("Recv Error"); return EXIT_FAILURE;
}
if (count == 0)
break;
printf("recv = %s\n",buf); //将听到的话打印出来
bzero(&buf,sizeof(buf)); //清空缓存
}
close(cli_fd);
close(sev_fd);
return EXIT_SUCCESS;
}
此段代码较简单,但是体现了服务器端 编程的基本流程,实现的功能就是将客户端发过来的数据输出打印在屏幕上。
2)、客户端的编程也是流程化操作
1、创建一个套接字(员工)
2、设置端口和IP(告诉员工老板的办公室在什么地方)
3、连接客户端(去找老板谈话)
4、发送数据或接收数据(和老板那么交谈)
代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
int main(void)
{
int sock,i = -1;
struct sockaddr_in addr;
char buf[256];
//创建套接字
if ((sock = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
perror("Socket Error"); return EXIT_FAILURE;
}
//设置IP和端口
addr.sin_family = AF_INET; //设置地址类型为IP
addr.sin_port = htons(8080); //设置端口
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //设置IP地址
memset(addr.sin_zero,0,sizeof(addr.sin_zero)); //清空填充字节
//客户端连接服务器
if (connect(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr_in)) == -1)
{
perror("Connect Error"); return EXIT_FAILURE;
}
while(1)
{
//设置待发送内容
memset(buf,0,sizeof(buf));
scanf("%s",buf);
//向服务器发送数据
if (send(sock, buf, strlen(buf),0) == -1)
{
perror("Send Error"); return EXIT_FAILURE;
}
}
close(sock);
return EXIT_SUCCESS;
}
这样就实现了客户端给服务器端发送数据,服务器端将接收到的数据打印在屏幕上。
一个小小的client/server模型的程序就这样写好了。