C++实现CS模型(计算机网络) |
您所在的位置:网站首页 › cs架构开发语言 › C++实现CS模型(计算机网络) |
文章目录
UDP实现CSUDP_server创建、初始化socket准备接受数据开始接/发数据
UDP_client创建、初始化socket准备接受数据开始发/接数据
TCP实现CSTCP_Client创建、初始化socket创建连接&准备发/收数据
TCP_Server创建、初始化socket接受数据发送数据
Source codeUDP_serverUDP_ClientTCP_ClientTCP_server
阿里嘎多,来为计网实验做个准备 本文代码运行环境为 linux系统 你可以在我的github仓库中找到源代码,或者在本文底部 可以star一波 小声bb 要构建一个应用程序 首先要选择它的结构,有两种典型架构: CS Client-Server 和 P2P peer to peer。其中CS架构是我们最常接触和使用到的。 接下来我们要实现进程间通信。 这就是今天我们要干的事情:在CS架构下实现 Client与server的通信。 网络进程间通信是通过 socket(应用层与运输层之间的接口) 来向网络 发送/接收 报文实现的。 大多数语言都为我们提供了socket API。 我们能做的就是 使用这些API,选择运输层参数,实现通信。 UDP实现CS在这部分我们实现一个 server将client发送内容转化为大写并返回的功能 UDP_server首先分析一下 UDP协议下server需要做什么。 创建socket,绑定自己的ip和端口。 这是server和client都需要做的 *应用层必须按协议栈向下运行才能实现通信。*而socket正是这个应用层与下层的接口。从socket读取client发送来的内容。通过socket,确定目的地(client的ip和端口号),发送响应内容。接下来我们来一步步实现 创建、初始化socket //创建Udp_socket,socket函数来自 sys/socket.h, IPPOROTO_UDP来自netinet/in.h int Udp_socket=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);socket函数原型为: int socket(int af, int type, int protocol);af代表地址族(IP),一般为ipv4或ipv6 其中AF_INET代表IPV4 ip地址,SOCK_DGRAM表示是无保障传输,protocol即运输协议。 我们在这里就是声明了一个UDP的socket for more information。 为了能让client能访问到我们,我们使用bind函数进行绑定,将server的套接字与一个IP和一个端口相连。 struct sockaddr_in server_addr; // struct sockaddr_in{ // sa_family_t sin_family; //地址族(Address Family),也就是地址类型 // uint16_t sin_port; //16位的端口号 // struct in_addr sin_addr; //32位IP地址 // char sin_zero[8]; //不使用,一般用0填充 // }; // struct in_addr{ // in_addr_t s_addr; //32位的IP地址 // }; memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family=AF_INET; server_addr.sin_port=htons(1234);//转为大端序 server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//function from arpa/inet.h bind(Udp_socket,(struct sockaddr*)&server_addr,sizeof(server_addr));这里一下子多了很多内容,我们来看一下。 首先是结构体 sockaddr_in,他的内容已在上面代码写出。 首先是 sin_family成员,和sock函数的第一个参数含义相同,取值也要相同。IPV4, AF_INET sin_port为要绑定的端口号。理论取值为 0 ~65536,但因为 0 ~1023端口一般都分配给特点的应用,所 以尽量避免使用。 可以在这个范围里随意选一个 sin_addr竟然也是一个结构体…用来绑定IP bind函数原型: int bind(int sock, struct sockaddr *addr, socklen_t addrlen); //Linux关于sockaddr和sockaddr_in的区别详见: 这里 准备接受数据芜湖,我们终于结束了折磨人的初始化环节,接下来就简单了! 我们首先要申请缓冲区来读写数据,并申请一些变量。就像Linux中通过文件描述符读写文件也需要缓冲区一样 char recv_buf[50];//接受缓冲区 char send_buf[50];//发送缓冲区 int recv_num;//接收字节数 int send_num;//发送字节数 struct sockaddr_in client_addr;//客户地址 int len=sizeof(client_addr);//客户地址长度为了将数据发送给client,我们也需要他的IP和端口号这就是在这里声明一个 client_addr的原因。 开始接/发数据 while(true){ cout if(recv_buf[i]>='a'&&recv_buf[i] cout //创建Udp_socket,socket函数来自 socket.h, IPPOROTO_UDP来自in.h int Udp_socket=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); struct sockaddr_in sever_addr; // struct sockaddr_in{ // sa_family_t sin_family; //地址族(Address Family),也就是地址类型 // uint16_t sin_port; //16位的端口号 // struct in_addr sin_addr; //32位IP地址 // char sin_zero[8]; //不使用,一般用0填充 // }; memset(&sever_addr,0,sizeof(sever_addr)); sever_addr.sin_family=AF_INET; sever_addr.sin_port=htons(1234); sever_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//function from arpa/inet.h bind(Udp_socket,(struct sockaddr*)&sever_addr,sizeof(sever_addr)); cout cout cout cout //创建套接字 int sock = socket(AF_INET, SOCK_STREAM, 0); //向服务器(特定的IP和端口)发起请求 struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充 serv_addr.sin_family = AF_INET; //使用IPv4地址 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址 serv_addr.sin_port = htons(1234); //端口 connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); //读取服务器传回的数据 char buffer[40]; read(sock, buffer, sizeof(buffer)-1); printf("Message form server: %s\n", buffer); //关闭套接字 close(sock); return 0; } TCP_server #include #include #include #include #include #include #include int main(){ //创建套接字 int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //将套接字和IP、端口绑定 struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充 serv_addr.sin_family = AF_INET; //使用IPv4地址 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址 serv_addr.sin_port = htons(1234); //端口 bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); //进入监听状态,等待用户发起请求 listen(serv_sock, 20); //接收客户端请求 struct sockaddr_in clnt_addr; socklen_t clnt_addr_size = sizeof(clnt_addr); int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size); //向客户端发送数据 char str[] = "hello client!"; write(clnt_sock, str, sizeof(str)); //关闭套接字 close(clnt_sock); close(serv_sock); return 0; } |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |