C++实现CS模型(计算机网络)

您所在的位置:网站首页 cs架构开发语言 C++实现CS模型(计算机网络)

C++实现CS模型(计算机网络)

2024-01-18 15:53| 来源: 网络整理| 查看: 265

文章目录 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