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. 9 shell 退出状态

    退出状态和逻辑运算符的组合 Shell 逻辑运算符 举栗 命令的退出状态(exit statu)是指执行完Linux命令或shell函数后,该命令或函数返回给调用它的程序的一个比较小的整数值.if 语 ...

  2. Elasticsearch-04-master选举

    3.2 master选举机制 3.2.1 选举算法 1)bully算法 核心思想 假定所有的节点都具有一个可以比较的ID,通过比较这个ID来选举master 流程说明 节点向所有比自己ID大的节点发送 ...

  3. C#下通过wbemtest和WMI Code Cretor更加高效的访问WMI

    能找到这篇博客的,相信都是有操作WMI需求的了.但是不知道如何快速验证.并集成到C#来操作WMI.我们分为3步: ##第一步:官网(或跟硬件开发WMI的人沟通你需要的接口和参数定义,如果是和硬件开发的 ...

  4. Kong的API管理方式

    目录 Kong 的管理方式 1. kong的关键术语 Service: Route: Upstream: Target: API: Consumer: Plugin: 2. 如何通过配置KONG AP ...

  5. python 按行查找文本文件,找出答案,并提示置顶答案

    1.整理好答案文件为文本文件:不能有空行:每个题干前有数字做为题号:每个题答案第一个字符为字母,答案占一行import time import time import sys import os im ...

  6. box-shadow详解

    今天课堂上有学生问到box-shadow这个属性,那么下面我们就来详细的解说下这个属性它的用法,box-shadow是css3中的一个属性,它可以向框添加一个或多个阴影. 首先我们来看它的语法: bo ...

  7. springMVC-9-异常处理器和拦截器

    异常解析器: 用于统一处理 servlet 中的异常; 拦截器: 用于统一处理业务中需要统一处理的页面(比如登录判断等), 可抽取出来统一处理. 我们一般需要在每个页面都通过在session中寻找有无 ...

  8. CSAPP:bomblab

    BOMBLAB实验总结 CSAPP实验BOMB,很头疼,看不懂,勉强做完了. 答案是这样的: Border relations with Canada have never been better. ...

  9. Git的使用(六)

    前言 版本管理工具总结: 开发团队项目,对项目的版本进行管理. 使用过的版本管理工具: TFS.SVN与Git. TFS:管理项目,通过visual Studio管理源码,拉取分支,提交代码等.也可以 ...

  10. ELK:match 的底层转换

    在ES中,执行match搜索的时候,ES底层通常都会对搜索条件进行底层转换,来实现最终的搜索结果.如: GET /student/java/_search { "query": { ...