UDP socket编程
目前毕设要在Linux下做一个类似tomcat的高性能web容器,写这篇文章的时候,大概项目已经写了一小半了。
前半部分,我都是使用TCP来实现的。
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。目前我要处理的问题是报文处理后需要发送给本地的服务进程,这样的话,使用TCP效率就有点低了,而我对UDP的socket编程又不是特别了解,所以便打算写篇文章记录一下。
这两个的头文件是自定义的,其他几篇文章有源码。
// server.cpp #include "../include/hlib.h" #include "../include/ErrorSolve.h" using namespace std; int main(int argc, char **argv) { // 指定服务进程的port if(argc != 2) ErrorSolve::quit("usage: ./server <PORT>"); // 创建UDP套接字 int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd < 0) ErrorSolve::quit("socket error"); // 初始化服务进程的地址信息 sockaddr_in servaddr {sin_family:AF_INET, sin_port:htons(atoi(argv[1]))}; if(inet_pton(AF_INET, "127.0.0.1", (void *)&servaddr.sin_addr) < 0) ErrorSolve::quit("inet_pton error"); // 绑定套接字 if(bind(sockfd, (sockaddr *)&servaddr, sizeof(servaddr)) < 0) ErrorSolve::quit("bind error"); int n; char buf[MAXLINE]; // 从sockfd读取,并写入标准输出 for(;;) { if((n = recvfrom(sockfd, buf, MAXLINE, 0, (sockaddr *)NULL, NULL)) < 0) ErrorSolve::quit("recvfrom error"); buf[n] = '\0'; // 读到quit,则跳出循环 if(strcmp("quit", buf) == 0) break; printf("%s\n", buf); } exit(0); }
// client.cpp #include "../include/hlib.h" #include "../include/ErrorSolve.h" using namespace std; int main(int argc, char **argv) { // 指定服务进程的ip和port if(argc != 3) ErrorSolve::quit("usage: ./client <IP> <PORT>"); // 创建UDP套接字 int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd < 0) ErrorSolve::quit("socket error"); // 初始化目的服务进程的地址 sockaddr_in servaddr {sin_family:AF_INET, sin_port:htons(atoi(argv[2]))}; if(inet_pton(AF_INET, argv[1], (void *)&servaddr.sin_addr) < 0) ErrorSolve::quit("inet_pton error"); int n; char buf[MAXLINE]; // 从标准输入读入,并写给sockfd while(~scanf("%s", buf)) { if((n = sendto(sockfd, buf, strlen(buf), 0, (sockaddr *)&servaddr, sizeof(servaddr))) < 0) ErrorSolve::quit("sendto error"); // 读到quit,则跳出循环 if(strcmp("quit", buf) == 0) break; printf("send %d msg\n", n); } exit(0); }
这是一个十分简单的服务,客户端向服务端发送消息,服务端接收并将其打印出来。
首先,我们注意到socket函数的第二个参数使用了SOCK_DGRAM,这就表示创建了一个UDP套接字。
然后,会发现在服务端中,与TCP不同的是,我们并没有使用accept和listen函数,而是直接在主循环中调用recvfrom来接收client发来的报文。
客户端中也没有connect函数,直接使用sendto来向server发送报文。
实际运行程序时,会发现服务端不必在客户端之前运行。客户端直接向指定port发送消息,服务端只需要监听指定端口上是否有消息到来就行了。
确实是感觉效率比TCP高出不少,也不用等待最后的2MSL,不过有什么缺点还得慢慢体会。

更多精彩