失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Udp---模拟实现客户端与服务器通信

Udp---模拟实现客户端与服务器通信

时间:2019-04-22 02:56:30

相关推荐

Udp---模拟实现客户端与服务器通信

//客户端模块#include <iostream>#include <cstdio>//stdio.h#include <string>//std::string#include <unistd.h>//close接口#include <stdlib.h>//atoi接口#include <netinet/in.h>//地址结构定义#include <arpa/inet.h>//字节序转换接口#include <sys/socket.h>//套接字接口class UdpSocket{public:UdpSocket():_sockfd(-1){}//1. 创建套接字bool Socket() {//socket(地址域, 套接字类型,协议类型);//AF_INET-标识这是IPv4的通信,并且提供的是数据报传输服务,使用的协议是UDP协议_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if (_sockfd < 0) {perror("socket error");return false;}return true;}//2. 为套接字绑定地址信息bool Bind(const std::string &ip, uint32_t port) {//1. 定义IPv4地址结构struct sockaddr_in addr;addr.sin_family = AF_INET;//地址域,用于向bind接口表明这是一个ipv4地址结构addr.sin_port = htons(port);//网络字节序的端口信息addr.sin_addr.s_addr = inet_addr(ip.c_str());//网络字节序的IP地址信息//2. 绑定地址socklen_t len = sizeof(struct sockaddr_in);//bind(描述符, 统一地址结构sockaddr*, 地址信息长度)int ret = bind(_sockfd, (struct sockaddr*)&addr, len);if (ret < 0) {perror("bind error");return false;}return true;}//3. 发送数据bool Send(const std::string &data, const std::string &ip, uint16_t port) {//sendto(描述符,数据,长度,选项, 对端地址,地址长度)//1. 定义对端地址信息的ipv4地址结构struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr(ip.c_str());//2. 向这个地址发送数据int ret;socklen_t len = sizeof(struct sockaddr_in);ret = sendto(_sockfd, data.c_str(), data.size(), 0, (struct sockaddr*)&addr, len);if (ret < 0) {perror("sendto error");return false;}return true;}//4. 接收数据bool Recv(std::string *buf, std::string *ip = NULL, uint16_t *port = NULL) {//recvfrom(描述符,缓冲区,数据长度,选项,对端地址,地址长度)struct sockaddr_in addr;//用于获取发送端地址信息socklen_t len = sizeof(struct sockaddr_in);//指定地址长度以及获取实际地址长度int ret;char tmp[4096] = {0};//临时用于存放数据的缓冲区ret = recvfrom(_sockfd, tmp, 4096, 0, (struct sockaddr*)&addr, &len);if (ret < 0) {perror("recvfrom error");return -1;}buf->assign(tmp, ret);//给buf申请ret大小的空间,从tmp中拷贝ret长度的数据进去if (ip != NULL) {*ip = inet_ntoa(addr.sin_addr);//将网络字节序整数IP地址转换为字符串地址,返回}if (port != NULL) {*port = ntohs(addr.sin_port);}return true;}//5. 关闭套接字void Close() {close(_sockfd);_sockfd = -1;return ;}private://贯穿全文的套接字描述符int _sockfd;};#define CHECK_RET(q) if((q)==false){return -1;}int main(int argc, char *argv[]){if (argc != 3) {printf("em: ./udp_cli 192.168.122.132 9000\n");return -1;}std::string ip_addr = argv[1];//服务端地址信息uint16_t port_addr = atoi(argv[2]);UdpSocket sock;CHECK_RET(sock.Socket());//创建套接字//CHECK_RET(sock.Bind());//绑定地址信息while(1) {//获取一个标准输入的数据,进行发送std::cout << "client say: ";fflush(stdout);std::string buf;std::cin >> buf;// 获取标准输入的数据sock.Send(buf, ip_addr, port_addr);//向指定的主机进程发送buf数据buf.clear();//清空buf缓冲区sock.Recv(&buf);//因为本身客户端就知道服务端的地址,因此不需要再获取了std::cout << "server say: " << buf << std::endl;}sock.Close();return 0;}

//服务端#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <netinet/in.h> //sockaddr结构体/ IPPROTO_UDP#include <arpa/inet.h> //包含一些字节序转换的接口#include <sys/socket.h>//套接字接口头文件int main(int argc, char *argv[]){//argc表示参数个数,通过argv向程序传递端口参数if (argc != 3) {printf("./udp_srv ip port em: ./udp_srv 192.168.122.132 9000\n");return -1;}const char *ip_addr = argv[1];uint16_t port_addr = atoi(argv[2]);//socket(地址域, 套接字类型, 协议类型)int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if (sockfd < 0) {perror("socket error");return -1;}//bind(套接字描述符, 地址结构, 地址长度);//struct sockaddr_in ipv4地址结构// struct in_addr{ uint32_t s_addr }; struct sockaddr_in addr;addr.sin_family = AF_INET;//htons-将两个字节的主机字节序整数转换为网络字节序的整数addr.sin_port = htons(port_addr);//注意千万不要使用htonl//inet_addr 将一个点分十进制的字符串IP地址转换为网络字节序的整数IP地址addr.sin_addr.s_addr = inet_addr(ip_addr);socklen_t len = sizeof(struct sockaddr_in);//获取IPv4地址结构长度int ret = bind(sockfd, (struct sockaddr*)&addr, len);if (ret < 0) {perror("bind error");return -1;}while(1) {char buf[1024] = {0};struct sockaddr_in cliaddr;socklen_t len = sizeof(struct sockaddr_in);//recvfrom(描述符,缓冲区,长度,参数,客户端地址信息, 地址信息长度)//阻塞接收数据,将数据放入buf中,将发送端的地址放入cliaddr中int ret = recvfrom(sockfd, buf, 1023, 0, (struct sockaddr*)&cliaddr,&len);if (ret < 0) {perror("recfrom error");close(sockfd);//关闭套接字return -1;}printf("client say: %s\n", buf);printf("server say:");fflush(stdout);//让用户输入数据,发送给客户端memset(buf, 0x00, 1024); //清空buf中的数据scanf("%s", buf);//通过sockfd将buf中的数据发送到cliaddr客户端ret =sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&cliaddr, len);if (ret < 0) {perror("sendto error");close(sockfd);//关闭套接字return -1;}}close(sockfd);//关闭套接字}

如果觉得《Udp---模拟实现客户端与服务器通信》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。