1.udp协议:用户数据报---无连接,传输不可靠,面向数据报。
实现不可靠链接,传输不够灵活,但是不存在数据粘包问题。
2.udp客户端与服务端通信流程
3.代码实现
//udp客户端
#include "udpsocket.hpp"
int main(int argc, char *argv[])
{
if (argc != 3) {
std::cout<<"./udp_cli ip port\n";
return -1;
}
std::string srv_ip = argv[1];
uint16_t srv_port = atoi(argv[2]);
UdpSocket sock;
CHECK_RET(sock.Socket());
while(1) {
std::string buf;
std::cout<<"client say:";
fflush(stdout);
std::cin >> buf;
sock.Send(buf, srv_ip, srv_port);
buf.clear();
sock.Recv(buf, srv_ip, srv_port);
std::cout<<"server say:"<<buf<<std::endl;
}
sock.Close();
return 0;
}
//udp服务端
#include "udpsocket.hpp"
int main(int argc, char *argv[])
{
if (argc != 3) {
printf("./udp_srv ip port\n");
return -1;
}
std::string srv_ip = argv[1];
uint16_t srv_port = atoi(argv[2]);
UdpSocket sock;
CHECK_RET(sock.Socket());
CHECK_RET(sock.Bind(srv_ip, srv_port));
while(1) {
std::string cli_ip;
uint16_t cli_port;
std::string buf;
sock.Recv(buf, cli_ip, cli_port);
printf("client[%s:%d]--say:%s\n", cli_ip.c_str(), cli_port,
buf.c_str());
buf.clear();
printf("server say:");
fflush(stdout);
std::cin >> buf;
sock.Send(buf, cli_ip, cli_port);
}
sock.Close();
return 0;
}
//头文件部分
/*===============================================================
* Copyright (C) . All rights reserved.")
* 文件名称:
* 创 建 者:zhang
* 创建日期:
* 描 述:ind(int sockfd, const struct sockaddr *addr,)ind(int sockfd, const struct sockaddr *addr,)实现封装一个UdpSocket类,向外提供方便的套接字操作接口
* bool Socket() 创建套接字
* bool Bind(std::string &ip, uint16_t port)
* bool Recv(std::string &buf, std::string &ip, uint16_t port)
* bool Send(std::string &buf, std::string &ip, uint16_t port)
* bool Close()
================================================================*/
#include <iostream>
#include <string>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
class UdpSocket
{
public:
UdpSocket():_sockfd(-1){
}
~UdpSocket(){
close(_sockfd);
}
bool Socket() {
_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (_sockfd < 0) {
perror("socket error");
return false;
}
return true;
}
bool Bind(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 = bind(_sockfd, (sockaddr*)&addr, len);
if (ret < 0) {
perror("bind error");
return false;
}
return true;
}
bool Recv(std::string &buf, std::string &ip, uint16_t &port) {
char tmp[4096] = {0};
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
int ret = recvfrom(_sockfd, tmp, 4096, 0, (sockaddr*)&addr,
&len);
if (ret < 0) {
perror("recv error");
return false;
}
buf.assign(tmp, ret);
ip = inet_ntoa(addr.sin_addr);
port = ntohs(addr.sin_port);
return true;
}
bool Send(std::string &buf, 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, buf.c_str(), buf.size(), 0,
(struct sockaddr*)&addr, len);
if (ret < 0) {
perror("sendto error");
return false;
}
return true;
}
bool Close() {
if (_sockfd >= 0){
close(_sockfd);
_sockfd = -1;
}
}
private:
int _sockfd;
};