udpsocket.hpp
/*
* 封装udpsocket类,通过实例化的对象,
* 调用自己的类成员接口可以在外部更加简单地完成客户端与服务端的搭建
*/
#include<cstdio>
#include<iostream>
#include<string>
#include<unistd.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/socket.h>
class UdpSocket
{
private:
int _sockfd;
public:
UdpSocket():_sockfd(-1){}
bool Socket()
{
_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(_sockfd<0)
{
perror("socket error\n");
return false;
}
return true;
}
bool Bind(const std::string &ip, uint16_t port)
{
struct sockaddr_in addr;
addr.sin_family = AF_FILE;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
socklen_t len = sizeof(struct sockaddr_in);
int ret = bind(_sockfd,(struct sockaddr*)&addr,len);
if(ret<0)
{
perror("bind error\n");
return false;
}
return true;
}
bool Send(const std::string &data,const std::string &ip, uint16_t port )
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
socklen_t len = sizeof(struct sockaddr_in);
int ret = sendto(_sockfd, data.c_str(),data.size(),0,(struct sockaddr*)&addr,len);
if(ret<0)
{
perror("sendto error");
return false;
}
printf("发送成功\n");
return true;
}
bool Recv(std::string *buf, std::string *ip=NULL, uint16_t *port=NULL)
{
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
char tmp[4096] = {0};
int ret = recvfrom(_sockfd,tmp,4096,0,(struct sockaddr*)&addr,&len);
//int ret= recvfrom(_sockfd,tmp,4096,0,(struct sockaddr*)&addr,&len);
if(ret<0)
{
perror("recv error\n");
return false;
}
buf->assign(tmp,ret);//申请空间并拷贝数据到buf
if(ip != NULL)
{
*ip= inet_ntoa(addr.sin_addr);
}
if(port != NULL)
{
*port = ntohs(addr.sin_port);
}
return true;
}
bool Close()
{
if(_sockfd != -1)
{
close(_sockfd);
}
return true;
}
};
udp_srv.c
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>//字节序转换接口头文件
#include<netinet/in.h>//地址结构协议类型头文件
#include<sys/socket.h>//socket接口头文件
int main()
{
//1. 创建套接字
//int sockei(地址域类型,套接字类型,协议类型)
int sockfd = socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP);
if(sockfd<0)
{
perror("socket error");
return -1;
}
//2.绑定地址信息
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(9000);//将主机字节序转换成网络字节序
addr.sin_addr.s_addr = inet_addr("10.0.4.7");
socklen_t len = sizeof(struct sockaddr_in);
// int bind(描述符,地质结构,地址长度)
int ret = bind(sockfd,(struct sockaddr*)&addr,len);
if(ret<0)
{
perror("bind error");
return -1;
}
while(1)
{
//3.接收数据
//recvfrom(描述符,空间,长度,标志位,对端地址,长度)
char buf[1024] = {0};
struct sockaddr_in peer_addr;
ret = recvfrom(sockfd,buf,1023,0,(struct sockaddr*) &peer_addr,&len);
if(ret<0)
{
perror("recvfrom error\n");
close(sockfd);
return -1;
}
printf("client-[%s:%d] say:%s\n",
inet_ntoa(peer_addr.sin_addr),
ntohs (peer_addr.sin_port),
buf);
//4.发送数据
memset(buf,0x00,1024);
printf("Sever say:");
fflush(stdout);
fgets(buf,1023,stdin);
ret = sendto(sockfd, buf, strlen(buf),0,(struct sockaddr*) &peer_addr,len);
if(ret<0)
{
perror("sendto error\n");
close(sockfd);
return -1;
}
}
//5.关闭套接字
close(sockfd);
return 0;
}
udp_cli.cpp
#include "udp_socket.hpp"
#define CHECK_RET(q) if((q)==false){return -1;}
int main()
{
//1.创建套接字
UdpSocket sock;
CHECK_RET(sock.Socket());
//2.绑定地址信息(不推荐)
while(1)
{
//3.发送数据
std::string buf;
std::cout<<"client say: ";
std::cin>>buf;
CHECK_RET(sock.Send(buf,"10.0.4.7",9000));
//4.接收数据
buf.clear();
CHECK_RET(sock.Recv(&buf));
std::cout<<"server say: "<<buf<<std::endl;
}
//5.关闭套接字
CHECK_RET(sock.Close());
return 0;
}