UDP特点
无连接,面向数据报(基于消息,不会粘包)的数据传输服务;
不可靠(可能会丢包),但一般情况下UDP更加高效;
UDP客户/服务基本模型
UDP基础API
1.Recvfrom
SYNOPSIS
#include <sys/types.h> #include <sys/socket.h> ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
2.Sendto
SYNOPSIS
#include <sys/types.h> #include <sys/socket.h> ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
实践:一个简陋的echo回声server/client
//server.cpp #include "commen.h" int main() { //创建UDP socket int sockfd = socket(AF_INET,SOCK_DGRAM,0); if (sockfd == -1) { err_exit("socket error"); } //填写server端信息 struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(9001); serverAddr.sin_addr.s_addr =INADDR_ANY; //绑定server端端口号 if (bind(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == -1) { err_exit("bind error"); } char buf[BUFSIZ]; struct sockaddr_in peerAddr; socklen_t peerLen = sizeof(peerAddr); while (true) { memset(buf,0,sizeof(buf)); int readCount = 0; //接收从客户端发送过来的数据 if ((readCount = recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&peerAddr,&peerLen)) == -1) { err_exit("recvfrom error"); } //打印客户端信息 cout << "Client: " << endl; cout << "\tsin_port: " << ntohs(peerAddr.sin_port) << endl; cout << "\tsin_addr: " << inet_ntoa(peerAddr.sin_addr) << endl; //将客户端发送来的信息回写回去 if (sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&peerAddr,peerLen) == -1) { err_exit("sendto error"); } buf[readCount] = 0; //输出到屏幕 fputs(buf,stdout); } return 0; }
//client.cpp #include "commen.h" int main() { //创建UDP socket int sockfd = socket(AF_INET,SOCK_DGRAM,0); if (sockfd == -1) { err_exit("socket error"); } //填写server端信息 struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(9001); serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); char buf[BUFSIZ]; //从键盘接收数据 while (fgets(buf,sizeof(buf),stdin) != NULL) { //向server端传送数据 if (sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == -1) { err_exit("sendto error"); } memset(buf,0,sizeof(buf)); int readCount = 0; //从server端接收数据,并且忽略server端信息recvfrom(xx,xx,xx,xx,NULL,NULL) if ((readCount = recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL)) == -1) { err_exit("recvfrom error"); } buf[readCount] = 0; //将数据写到屏幕 fputs(buf,stdout); } return 0; }
实验结果:
查看端口:
附-commen.h
#ifndef COMMEN_H_INCLUDED #define COMMEN_H_INCLUDED #include <unistd.h> #include <signal.h> #include <errno.h> #include <fcntl.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/msg.h> #include <sys/sem.h> #include <sys/socket.h> #include <sys/select.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <iostream> using namespace std; void err_exit(std::string str) { perror(str.c_str()); exit(EXIT_FAILURE); } void peerClosePrint(std::string str = "peer connect closed") { cerr << str << endl; _exit(0); } #endif // COMMEN_H_INCLUDED
附-Makefile
CC = g++ CPPFLAGS = -Wall -g -pthread BIN = server client SOURCES = $(BIN.=.cpp) .PHONY: clean all all: $(BIN) clean: -rm -rf $(BIN) bin/ obj/ core
时间: 2024-11-05 16:08:48