当前位置:网站首页>Socket programming UDP
Socket programming UDP
2022-06-12 11:22:00 【Diligent_ wu】
Network communication process simulation

Quintuples : Each piece of data of a host must contain five pieces of information , Source end public network IP、 Source end port、 Peer to peer public network IP、 Opposite end port、 Protocol scheme
UDP Communication programming
udp Communication programming process :
simulation socket Port binding process :
socket Interface
int socket(int domain,int type,int protocol);
int bind(int sockfd,struct sockaddr* _addr,socklen_t len);
ssize_t recvfrom(int sockfd,char *buf,int len,int flag,struct sockaddr *peer_addr,socklen_t *addrlen )
ssize_t sendto(int sockfd,char* data,int len, int flag,struct sockaddr* peer_addr,socklen_t addlen);
1. Create socket
int socket(int domain,int type,int protocol);
domain: Address field - Make sure this time socket Which protocol version of the address structure is used for communication - Different protocols have different address structures -- AF_INET IPV4 Network protocol ;
type: Socket type ( Streaming socket SOCK_STREAM / Datagram socket SOCK_DGRAM(datagram) )
protocol: Protocol type ( Generally, it is the choice of transport layer protocol IPPROTO_TCP = 6 /IPPROTO_UDP = 17) The default is 0,type After giving it ,protocol You can give 0 了 .
protocol stay /usr/include/netinet/in.h The following definition
Return value : Returns a file descriptor ( socket descriptor ) – Non-negative integer , Through this descriptor, you can find the corresponding socket Structure . Failure to return -1.
2. Binding address information for socket
int bind(int sockfd,struct sockaddr* _addr,socklen_t len);
sockfd: Create the operation handle returned by the socket
addr: Address information to bind
len: Length of address information to be bound
Return value : Bind successfully returned 0, Binding failed and returned -1.
Address structure :(/usr/include/netinet/in.h:221、240)
struct sockaddr{
sa_family_t sa_family;
char sa_data[4];
}

struct sockaddr This structure , Contains two members , One is the address field , One is data .
We usually use AF_INET、AF_INET6 and AF_LOCAL fill , The three macros correspond to one structure , It contains different information . The first member of their structure is the same , Is an address field type , And you can bind different address information only by ensuring the address domain .
bind Different types can be bound , In order to achieve interface unification , So when the user defines the address structure , Define the address structure you need ( for example :ipv4 Just use struct sockaddr_in), But when Binding , Unification will force the type to sockaddr* type .
bind Internal implementation guess :
bind(fd,struct sockaddr* addr,len){
if(addr->sa_family == AF_INET){// binding IPV4 Address information , This structure follows sockadd_in To analyze }
else if(addr->sa_family == AF_UNET6){//IPV6, according to IPV6 Address structure resolution }
else if(addr->sa family == AF_LOCAL){}
3. receive data
Not just receiving data , We also need to know who sent the data , In order to reply
ssize_t recvfrom(int sockfd,char *buf,int len,int flag,struct sockaddr *peer_addr,socklen_t *addrlen )
sockfd: Socket operation handle
buf: Receive buffer
len: The length of data you want to accept
flag: The default is 0, It means blocking . If there is no data , Just waiting for .
peer_addr: Address information of the sender
addrlen: The length of the address information you want to get and the actual length returned ( Input/output parameter )
Return value : The length of the actually received data bytes is returned successfully , Failure to return -1;
4. send data
ssize_t sendto(int sockfd,char* data,int len, int flag,struct sockaddr* peer_addr,socklen_t addlen);
data: The first address of the data to be sent
peer_addr: The recipient's address information
Return value : The length of the actually received data bytes is returned successfully , Failure to return -1;
5. Close socket
close(int sockfd);
Byte order conversion interface
Conversion from host byte order to network byte order :
uint16_t htons(uint16_t data); Short
uint32_t htonl(uint32_t data); Long integer
Conversion from network byte order to host byte order :
uint16_t ntohs(unit16_t data); Short
uint32_t ntohl(uint32_t data); Long integer
character string IPV4 Of IP Address conversion to network byte order IP Address :
in_addr_t It's a uint32_t type
in_addr_t inet_addr(char* ip);
Integer of network byte order IP Address to string IPV4 Of IP Address :
char* inet_ntoa(struct in_addr_t nip);
Be careful :16 For bit conversion htons/ntohs
32 For bit conversion htonl/ntohl
Can't mix !!!
Will cause byte order disorder .
4 Number of bytes used htons/ntohs, Only two bytes are cut out , Do byte order conversion , Then complete it , As a result, the data obtained are not in line with expectations . It's wrong. .
2 Number of bytes used htonl/ntohl, Carry out 4 Byte converted , Only two bytes will be completed first , It's changing , If you use 16 Bit data , Will only take the lower 16 A data . It's also wrong .
Simple and easy UDP Communication process
socket Class encapsulation
Encapsulates a udpSocket class , Every instantiated object is a udp Communication connection , Complete the communication process through the member methods of this object .
class udpSocket{
public:
udpSocket():_sockfd(-1){}
bool Socket();
bool Bind(const str::string& ip,uint16_t port);
bool Recvfrom(std::string* buf,std::string* ip,uint16_t* port);
bool sendto(std::string& data,std::string& ip,uint16_t port);
bool Close();
private:
int _sockfd;
}
#include<cstdio>
#include<unistd.h>
#include<string>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
class UdpSocket
{
public:
UdpSocket():_sockfd(-1){
}
public:
//1. Create socket
bool Socket()
{
//socket( Address field , Socket type , Protocol type )
_sockfd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if(_sockfd < 0)
{
perror("socket error");
return false;
}
return true;
}
//2. Binding address information
bool Bind(const std::string& ip,uint16_t port)
{
// Definition IPV4 Address structure information
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
// Address structure size
socklen_t len = sizeof(struct sockaddr_in);
//bind( socket descriptor , Address structure , Address structure size )
int ret = bind(_sockfd,(struct sockaddr*)&addr,len);
if(ret < 0 )
{
perror("bind error");
return false;
}
return true;
}
// receive data
bool Recvfrom(std::string* buf, std::string* ip = NULL,uint16_t* port = NULL)
{
// Create an address structure
struct sockaddr_in peer_addr;
socklen_t len = sizeof(sockaddr_in);
// Create buffer
char tmp[4096]={
0};
//recvfrom( socket descriptor , Receive buffer , Buffer size , identifier , Address structure information , Address structure size )
ssize_t ret = recvfrom(_sockfd,tmp,4096,0,(struct sockaddr*)&peer_addr,&len) ;
buf->assign(tmp,ret); // from tmp Medium intercept ret The length of the data is put into buf in
if(ret < 0)
{
perror("recvfrom error");
return false;
}
if(ip != NULL)
{
*ip = inet_ntoa(peer_addr.sin_addr); // If it comes in ip yes NULL Of , Just put peer_addr Of ip Give it
}
if(port!= NULL)
{
*port = ntohs(peer_addr.sin_port);
}
return true;
}
//4. send data
bool Sendto(std::string& data,std::string& ip,uint16_t port)
{
// Create an address structure
struct sockaddr_in peer_addr;
peer_addr.sin_family = AF_INET;
peer_addr.sin_port = htons(port);
peer_addr.sin_addr.s_addr = inet_addr(ip.c_str());
socklen_t len = sizeof(struct sockaddr_in);
//sendto( Socket identifier , Send buffer , Buffer size , identifier , Address structure information , Address structure size )
ssize_t ret = sendto(_sockfd,data.c_str(),data.size(),0,(struct sockaddr*)&peer_addr,len);
if(ret < 0 )
{
perror("sendto error");
return false;
}
return true;
}
//5. Close socket
bool Close()
{
if(_sockfd > 0 )
{
close(_sockfd);
_sockfd = -1;
}
return true;
}
private:
int _sockfd;
};
The communication process of the server
#include<iostream>
#include<string>
#include"Udpsocket.hpp"
#define CHECK_RET(p) if((p) == false){
return false;}
int main(int argc, char*argv[])
{
// Get orders
// ./udp_srv 192.168.116.128 9000
if(argc != 3)
{
std::cout<<"Usage: ./udp_srv ip port";
return -1;
}
uint16_t port = std::stoi(argv[2]);
std::string ip = argv[1];
// Demonstrate the socket server process
UdpSocket srv_socket;
// Create socket
CHECK_RET(srv_socket.Socket());
// Binding address information
CHECK_RET(srv_socket.Bind(ip,port));
while(1)
{
// receive messages
std::string buf;
std::string peer_ip;
uint16_t peer_port;
CHECK_RET(srv_socket.Recvfrom(&buf,&peer_ip,&peer_port)); // Accept peer address information
//clint[192.168.xxx.xxx 8000]say:
std::cout<<"clint["<<peer_ip<<" "<<peer_port<<"]say:"<<buf<<std::endl;
// Send a message
buf.clear();
std::cout<<"server say:";
std::cin>>buf;
CHECK_RET(srv_socket.Sendto(buf,peer_ip,peer_port)); // Reply to whoever sends the data
}
// Close socket
CHECK_RET(srv_socket.Close());
return 0;
}
Client communication flow
#include<iostream>
#include<string>
#include"Udpsocket.hpp"
#define CHECK_RET(p) if((p) == false){
return false;}
int main(int argc,char* argv[])
{
if(argc != 3)
{
std::cout<<"Usage: ./udp_cli ip port";
return -1;
}
std::string srv_ip = argv[1];
uint16_t srv_port = std::stoi(argv[2]);
UdpSocket cli_socket;
CHECK_RET(cli_socket.Socket());
//CHECK_RET(cli_socket.Bind(ip,port));
while(1)
{
std::cout<<"client say:";
std::string buf;
std::cin>>buf;
CHECK_RET(cli_socket.Sendto(buf,srv_ip,srv_port));
buf.clear();
CHECK_RET(cli_socket.Recvfrom(&buf));
std::cout<<"server say: "<<buf<<std::endl;
}
CHECK_RET(cli_socket.Close());
return 0;
}
边栏推荐
- MCUXpresso开发NXP RT1060(3)——移植LVGL到NXP RT1060
- Arm cross compilation chain download address
- Zabbix 监控之LLD
- 人類想要擁有金錢、權力、美麗、永生、幸福……但海龜只想做一只海龜
- arm交叉编译链下载地址
- tensorflow 2. X multi classification confusion matrix and evaluation index calculation method (accuracy rate, recall rate, F1 score)
- AI - face
- 命名规范/注释规范/逻辑规范
- Selenium uses proxy IP
- DS18B20数字温度计 (一) 电气特性, 供电和接线方式
猜你喜欢

MATLAB中stairs函数使用

Reading mysql45 lecture - self summary (part)

M-Arch(番外11)GD32L233评测-PWM驱动有源蜂鸣器

Vite Basics

k52.第一章 基于kubeadm安装kubernetes v1.22 -- 集群部署

AcWing 131. The largest rectangle in the histogram (monotone stack classic application template)

The most detailed explanation of the top ten levels of sqli labs platform

MYSQL——内置函数

890. find and replace mode

Les humains veulent de l'argent, du pouvoir, de la beauté, de l'immortalité, du bonheur... Mais les tortues ne veulent être qu'une tortue.
随机推荐
【clickhouse专栏】基础数据类型说明
Humans want to have money, power, beauty, eternal life and happiness... But turtles only want to be a turtle
Handwritten common interview questions
FPGA开发——Hello_world例程
logrotate日志轮转方式create和copytruncate原理
M-Arch(番外11)GD32L233评测-PWM驱动有源蜂鸣器
^33 variable promotion and function promotion interview questions
Collation of common functions in JS
35. 搜索插入位置
go基于腾讯云实现发送短信
【clickhouse专栏】基础数据类型说明
Thinking about the cooperation process of Network Library -- Some Thoughts on reading brpc
Arm cross compilation chain download address
C# 36. DataGridView行号
tensorflow 2. X multi classification confusion matrix and evaluation index calculation method (accuracy rate, recall rate, F1 score)
基于C#的安全聊天工具设计
十折交叉验证代码中的问题
redis 总结
Zabbix 监控之LLD
Common port description