56.1 UDP 编程模型

56.1.1 编程模型

  UDP 协议称为用户数据报文协议,可靠性比 TCP 低,但执行效率高

  

56.1.2 API

(1)发送数据

  

  • 函数参数:

    • sockfs:套接字文件描述符
    • buf:发送的数据
    • len:发送的数据的大小,即多少个字节
    • flags:一般设置为0
    • dest_addr:接收方的地址
    • addrlen:前面地址结构体 dest_addr 的大小
    • msg:将发送的数据封装在 msghdr 的结构体中
  • 返回值:返回值都一样,成功,则返回发送的字节数;出错,则返回-1

  

(2)接收数据

  

  • 返回值:返回消息的字节数,无消息,返回0;出错返回 -1

56.2 例子

56.2.1 服务器编程

  time_udp_server.c

 #include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <time.h> int sockfd; void sig_handler(int signo)
{
if(signo == SIGINT){
printf("server close\n");
close(sockfd);
exit();
}
} void out_addr(struct sockaddr_in *clientaddr)
{
char ip[];
int port;
memset(ip, , sizeof(ip));
inet_ntop(AF_INET, &clientaddr->sin_addr.s_addr, ip, sizeof(ip));
port = ntohs(clientaddr->sin_port);
printf("client: %s(%d)\n", ip, port);
} /** 和客户端进行通信 */
void do_service(int fd)
{
struct sockaddr_in clientaddr;
socklen_t len = sizeof(clientaddr);
char buffer[];
memset(buffer, , sizeof(buffer));
/** 接收客户端的数据报文 */
if(recvfrom(sockfd, buffer, sizeof(buffer), , (struct sockaddr *)&clientaddr, &len) < ){
perror("recvfrom error");
}
else{
out_addr(&clientaddr);
printf("client send into: %s\n", buffer); /** 向客户端发送数据报文 */
long int t = time();
char *ptr = ctime(&t);
ssize_t size = strlen(ptr) * sizeof(char);
if(sendto(sockfd, ptr, size, , (struct sockaddr *)&clientaddr, len) < ){
perror("sendto error");
}
} } int main(int argc, char *argv[])
{
if(argc < ){
printf("usage: %s port\n", argv[]);
exit();
} if(signal(SIGINT, sig_handler) == SIG_ERR){
perror("signal sigint error");
exit();
} /** 步骤1: 创建 socket */
sockfd = socket(AF_INET, SOCK_DGRAM, );
if(sockfd < ){
perror("socket error");
exit();
} int ret;
int opt = ;
/** 设置套接字选项, 让停掉的端口马上可以使用 */
if((ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < ){
perror("setsockopt error");
exit();
} /** 步骤2: 调用 bind 函数对 socket 和地址进行绑定 */
struct sockaddr_in serveraddr;
memset(&serveraddr, , sizeof(serveraddr));
serveraddr.sin_family = AF_INET; ///< ipv4
serveraddr.sin_port = htons(atoi(argv[1])); ///< port
serveraddr.sin_addr.s_addr = INADDR_ANY; ///<IP
if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0){
perror("bind error");
exit();
} /** 步骤3: 和客户端进行双向的数据通信 */
while(){
do_service(sockfd);
} return ;
}

56.2.2 客户端编程

  time_udp_client.c

 #include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <time.h> int main(int argc, char *argv[])
{
if(argc < ){
printf("usage: %s ip port\n", argv[]);
exit();
} /** 步骤1: 创建 socket */
int sockfd = socket(AF_INET, SOCK_DGRAM, );
if(sockfd < ){
perror("socket error");
exit();
} /** 步骤2: 调用 recvfrom 和 sendto 等函数和服务器端双向通信 */
struct sockaddr_in serveraddr;
memset(&serveraddr, , sizeof(serveraddr));
serveraddr.sin_family = AF_INET; ///< ipv4
serveraddr.sin_port = htons(atoi(argv[2])); ///< port
inet_pton(AF_INET, argv[1], &serveraddr.sin_addr.s_addr);
char buffer[] = "hello world";
/** 向服务器端发送数据报文 */
if(sendto(sockfd, buffer, sizeof(buffer), , (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < ){
perror("sendto error");
exit();
}
else{
/** 接受服务器端发送的数据报文 */
memset(buffer, , sizeof(buffer));
if(recv(sockfd, buffer, sizeof(buffer), ) < ){
perror("recv error");
exit();
}
else{
printf("%s", buffer);
}
} close(sockfd); return ;
}

  编译运行测试:

  

最新文章

  1. SQL Server-聚焦APPLY运算符(二十七)
  2. Autocad 2012 win7(64位)启动时一直卡在acmgd.dll处的解决方案
  3. RobotFrameWork(四)变量运算与Evaluate
  4. [转载] 不查资料确定int型整数的最大值和最小值
  5. java中泛型上限,下限应用
  6. OSG-OSGEarth
  7. Map:containsKey、containsValue 获取Map集合的键值的 值
  8. mysql PDO的使用
  9. 【原】storm源码之理解Storm中Worker、Executor、Task关系
  10. C# 面向对象之概念理解(2)
  11. C#发送Email邮件(实例:QQ邮箱和Gmail邮箱)
  12. 出现 HTTP Error 503. The service is unavailable 错误
  13. iOS中 视频直播功能-流媒体的使用
  14. android Bitmap围绕一个点进行旋转
  15. 51nod贪心算法教程
  16. Linux整合Apache和SVN
  17. algs4 使用 DrJava 编写 Hello World on Windows
  18. Java_按位与&amp;,按位或,取反,左移,右移运算符
  19. java小技巧-生成重复的字符
  20. 前端开发 - CSS - 下

热门文章

  1. python 验证码识别库pytesseract的使用
  2. lodash源码分析之去重--uniq方法
  3. Redis和MongoDB的区别(面试受用)
  4. MySql 触发器的新增、修改、删除的创建
  5. fastJson反序列化异常,JSONException: expect &#39;:&#39; at 0, actual =
  6. 12 Django Rest Swagger生成api文档
  7. ABP之什么是ABP(ASP.NET Boilerplate)
  8. iis设置默认文档,提示web.config配置xml格式不正确
  9. [转帖]&quot;&quot;(双引号) 与&#39;&#39;(单引号) 差在哪?
  10. webmagic爬虫框架抽取元素