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. Spring Boot中文文档(官方文档翻译 基于1.5.2.RELEASE)

    作者:Phillip Webb, Dave Syer, Josh Long, Stéphane Nicoll, Rob Winch, Andy Wilkinson, Marcel Overdijk, ...

  2. bugku秋名山车神

    不断的刷新,发现表达式一直在变换,这种必须写脚本,才能跟上速度.直接上代码 import re import requests s=requests.session() r=s.get("h ...

  3. WPF教程一:创建Hello world来理解XAML的内容及编译

    在实际的WPF开发中遇到很多再用Winform写法来写WPF的开发人员,很多时候项目进度延期.出现非必要的BUG等等.大多是因为开发人员虽然是再写WPF. 但是没有好好的学过WPF,就导致无法发挥出W ...

  4. Java | 标识符 & 关键字

    标识符是什么? 标识符 标识符是指在程序中,我们自己定义的内容.比如类的名字.方法的名字和变量的名字等等,都是标识符.在我们写的第一个程序当中,我们给类起名叫做Hello 也叫做标识符. 命名规则 标 ...

  5. 「AGC020D」 Min Max Repetition

    「AGC020D」 Min Max Repetition 传送门 首先这个东西的连续字符个数你可以二分.但事实上没有必要,这是可以直接算出来的. 即 \(k=\max\{\lceil\frac{A}{ ...

  6. this的四种用法!

    经常会有人问到this的用法,其实简单来说,this有四种应用场景,分别是在构造函数上.对象属性中.普通函数中.call和apply方法中. 首先我们来看第一种:在构造函数中的用法 第二种是在在对象属 ...

  7. C语言变量为何先定义后使用

    C语言中,对变量的使用,首先要先定义.说明其数据类型.原因可能如下: 1不同类型的变量,其编码表示方式可能不同. 2不同类型的变量,其占有的空间大小不同.不事先说明无法在内存中开辟空间.

  8. Python自动化测试面试题-编程篇

    目录 Python自动化测试面试题-经验篇 Python自动化测试面试题-用例设计篇 Python自动化测试面试题-Linux篇 Python自动化测试面试题-MySQL篇 Python自动化测试面试 ...

  9. C++第三十六篇 -- 为第一个驱动程序进行调试

    工具是VMware12+Win10+VS2017+WDK1809 https://blog.csdn.net/qq_21763381/article/details/83242916 首先分清楚主计算 ...

  10. 关于maven打包与jdk版本的一些关系

    最近让不同JAVA版本的容器maven打包折腾的不行,终于理出了一点头绪.在这里记录下备忘. 1. Maven与jdk版本的关系 先明确一个概念,关高版本JDK运行maven,是可以打出低版本的JAV ...