UDP主要使用sendto()recvfrom()

recvfrom()

函数原型如下:

#include <sys/types.h>
#include <sys/socket.h> ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); if (recvfrom(sockfd_s, buf, BUFFERSIZE, 0, (struct sockaddr*)&client_addr, &addrlen) == -1) {
perror("recvfrom");
continue; //UDP无连接传输,偶尔传输失败一次继续执行
}

特别注意:

  • sockfd是本地套接字的描述符,在服务器端,就是服务器套接字;在客户端,就是客户端套接字
  • buf是接受数据的缓冲区,len是缓冲区的大小
  • flags一般为0
  • 后面两个参数是用来获取:数据发送端的IP地址和端口号

sendto()

函数原型如下:

#include <sys/types.h>
#include <sys/socket.h> ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); if (sendto(sockfd_c, buf, strlen(buf)+1, 0, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
perror("sendto");
continue;
}

特别注意:

  • sockfd是本地套接字的描述符,在发送的时候一般要绑定本地套接字与众所周知的IP地址和端口
  • 参数中的套接字地址就是要发送的目的

示例

server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h> #define SERVER_IP "172.17.44.154"
#define SERVER_PORT 5002
#define BUFFERSIZE 100 int main(int argc, const char *argv[])
{
int sockfd_s;
struct sockaddr_in server_addr, client_addr;
char buf[BUFFERSIZE];
socklen_t addrlen; /* 创建套接字 */
if ((sockfd_s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(-1);
} /* 绑定服务器套接字 */
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_family = AF_INET;
if (inet_pton(AF_INET, SERVER_IP, (void*)&server_addr.sin_addr.s_addr) != 1) {
perror("inet_pton");
exit(-1);
}
if (bind(sockfd_s, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("bind");
exit(-1);
} while (1) { bzero(buf, BUFFERSIZE);
if (recvfrom(sockfd_s, buf, BUFFERSIZE, 0, (struct sockaddr*)&client_addr, &addrlen) == -1) {
perror("recvfrom");
continue; //UDP无连接传输,偶尔传输失败一次继续执行
} else { //成功收到
if (strcmp(buf, "quit") == 0) {
printf("the client %s/%d is quit\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
exit(0);
}
printf("recv from %s/%d data:%s\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), buf); sendto(sockfd_s, buf, strlen(buf)+1, 0, (struct sockaddr*)&client_addr, (socklen_t)sizeof(client_addr)); //retroreflection
} } return 0;
}

client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h> #define SERVER_IP "172.17.44.154"
#define SERVER_PORT 5002
#define BUFFERSIZE 100 int main(int argc, const char *argv[])
{
int sockfd_c;
struct sockaddr_in server_addr;
char buf[BUFFERSIZE]; //512
socklen_t addrlen;
/* 创建套接字 */
if ((sockfd_c = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(-1);
} bzero(&server_addr, sizeof(server_addr));
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_family = AF_INET;
if (-1 == inet_pton(AF_INET, SERVER_IP, (void*)&server_addr.sin_addr.s_addr)) {
perror("inet_pton");
exit(-1);
} while (1) { bzero(buf, BUFFERSIZE);
printf("input:");
fgets(buf, BUFFERSIZE-1, stdin); if (sendto(sockfd_c, buf, strlen(buf)+1, 0, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
perror("sendto");
continue;
}
if (strcmp(buf, "quit\n") == 0) {
printf("the client will quit\n");
exit(0);
} bzero(buf, BUFFERSIZE);
// bzero(&server_addr, sizeof(server_addr));
if (-1 == recvfrom(sockfd_c, buf, BUFFERSIZE - 1, 0, (struct sockaddr*)&server_addr, &addrlen)) {
perror("recvfrom");
continue;
}
else {
printf("recv from %s/%d data:%s\n", inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port), buf);
} } return 0;
}

Linux UDP服务器编程的更多相关文章

  1. Linux 高性能服务器编程——I/O复用

    问题聚焦:     前篇提到了I/O处理单元的四种I/O模型.     本篇详细介绍实现这些I/O模型所用到的相关技术.     核心思想:I/O复用 使用情景: 客户端程序要同时处理多个socket ...

  2. Linux 高性能服务器编程——Linux网络编程基础API

    问题聚焦:     这节介绍的不仅是网络编程的几个API     更重要的是,探讨了Linux网络编程基础API与内核中TCP/IP协议族之间的关系.     这节主要介绍三个方面的内容:套接字(so ...

  3. Linux 高性能服务器编程——TCP协议详解

    问题聚焦:     本节从如下四个方面讨论TCP协议:     TCP头部信息:指定通信的源端端口号.目的端端口号.管理TCP连接,控制两个方向的数据流     TCP状态转移过程:TCP连接的任意一 ...

  4. Linux 高性能服务器编程——IP协议详解

    1 IP服务特点 IP协议是TCP/IP协议族的动力,它为上层协议提供无状态.无连接.不可靠的服务. 无状态:IP通信双方不同步传输数据的状态信息,因此IP数据包的发送.传输和接收都是无序的.     ...

  5. Linux 高性能服务器编程——TCP/IP协议族

    1 TCP/IP协议族体系结构 数据链路层:     职责:实现网卡接口的网络驱动程序,一处理数据在物理媒介(如以太网.令牌环等)上的传输.     常用协议:ARP协议(地址解析协议),RARP协议 ...

  6. linux高性能服务器编程 (一) --Tcp/Ip协议族

    前言: 在学习swoole入门基础的过程中,遇到了很多知识瓶颈,比方说多进程.多线程.以及进程池和线程池等都有诸多的疑惑.之前也有学习相关知识,但只是单纯的知识面了解.而没有真正的学习他们的来龙去脉. ...

  7. Linux 高性能服务器编程——多线程编程

    问题聚焦:     在简单地介绍线程的基本知识之后,主要讨论三个方面的内容:    1 创建线程和结束线程:    2 读取和设置线程属性:    3 线程同步方式:POSIX信号量,互斥锁和条件变量 ...

  8. Linux 高性能服务器编程——多进程编程

    问题聚焦:     进程是Linux操作系统环境的基础.     本篇讨论以下几个内容,同时也是面试经常被问到的一些问题:     1 复制进程映像的fork系统调用和替换进程映像的exec系列系统调 ...

  9. Linux 高性能服务器编程——高性能服务器程序框架

    问题聚焦:     核心章节.     服务器一般分为如下三个主要模块:I/O处理单元(四种I/O模型,两种高效事件处理模块),逻辑单元(两种高效并发模式,有效状态机)和存储单元(不讨论). 服务器模 ...

随机推荐

  1. 什么是BSE

    BSE (bridge system engineer) 是外包开发人员和客户之前的桥梁. 主要是将客户的需求准确的理解并传达给外包的开发人员,一般情况下也兼开发的 leader 工作. 参考: ht ...

  2. Linux学习之路第四天(运行级别)

    linux 实用指令 指定运行级别 运行级别说明 0 :关机 1:单用户(找回丢失密码) 2.多用户状态没有网络服务 3.多用户状态有网络服务 4.系统未保留给用户 5.图形界面 6.系统重启 常用的 ...

  3. WPF教程三:学习Data Binding把思想由事件驱动转变为数据驱动

    之前大家写代码都喜欢用事件驱动,比如说鼠标输入的click事件.初始化的内容全部放在窗体加载完毕的load事件,等等,里面包含了大量的由事件触发后的业务处理代码.导致了UI和业务逻辑高度耦合在一个地方 ...

  4. ESP32-http client笔记

    基于ESP-IDF4.1 #include <string.h> #include <stdlib.h> #include "freertos/FreeRTOS.h& ...

  5. http、tcp和socket简单理解

    1.Http属于应用层,主要解决如何包装数据. 2.Tcp属于传输层,主要解决数据如何在网络上传输. 3.Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API) ...

  6. linux驱动之LED驱动

    通过之前的学习,了解到linux驱动编写的流程是:先通过注册函数注册我们编写的入口函数,然后在入口函数中获取设备号->注册字符设备->自动创建设备节点->获取设备树信息,最后通过销毁 ...

  7. Lua控制语句

    目录 1. 控制结构 if-else 单个 if 分支 型 两个分支: if-else 型 多个分支: if-elseif-else型 2. while 型控制结构 3. repeat控制结构 4. ...

  8. CURL 实战下载

    #include <string> #include <stdio.h> #include <iostream> #include<fstream> # ...

  9. Django基础-02篇 Models的属性与字段

    1.models字段类型 AutoField():一个IntegerField,根据可用ID自动递增.如果没指定主键,就创建它自动设置为主键. IntegerField():一个整数: FloatFi ...

  10. C语言中函数的返回值

    规则 除局部变量的内存地址不能作为函数的返回值外,其他类型的局部变量都能作为函数的返回值. 我总结出下面这些规则: int.char等数据类型的局部变量可以作为函数返回值. 在函数中声明的指针可以作为 ...