Linux UDP服务器编程
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服务器编程的更多相关文章
- Linux 高性能服务器编程——I/O复用
问题聚焦: 前篇提到了I/O处理单元的四种I/O模型. 本篇详细介绍实现这些I/O模型所用到的相关技术. 核心思想:I/O复用 使用情景: 客户端程序要同时处理多个socket ...
- Linux 高性能服务器编程——Linux网络编程基础API
问题聚焦: 这节介绍的不仅是网络编程的几个API 更重要的是,探讨了Linux网络编程基础API与内核中TCP/IP协议族之间的关系. 这节主要介绍三个方面的内容:套接字(so ...
- Linux 高性能服务器编程——TCP协议详解
问题聚焦: 本节从如下四个方面讨论TCP协议: TCP头部信息:指定通信的源端端口号.目的端端口号.管理TCP连接,控制两个方向的数据流 TCP状态转移过程:TCP连接的任意一 ...
- Linux 高性能服务器编程——IP协议详解
1 IP服务特点 IP协议是TCP/IP协议族的动力,它为上层协议提供无状态.无连接.不可靠的服务. 无状态:IP通信双方不同步传输数据的状态信息,因此IP数据包的发送.传输和接收都是无序的. ...
- Linux 高性能服务器编程——TCP/IP协议族
1 TCP/IP协议族体系结构 数据链路层: 职责:实现网卡接口的网络驱动程序,一处理数据在物理媒介(如以太网.令牌环等)上的传输. 常用协议:ARP协议(地址解析协议),RARP协议 ...
- linux高性能服务器编程 (一) --Tcp/Ip协议族
前言: 在学习swoole入门基础的过程中,遇到了很多知识瓶颈,比方说多进程.多线程.以及进程池和线程池等都有诸多的疑惑.之前也有学习相关知识,但只是单纯的知识面了解.而没有真正的学习他们的来龙去脉. ...
- Linux 高性能服务器编程——多线程编程
问题聚焦: 在简单地介绍线程的基本知识之后,主要讨论三个方面的内容: 1 创建线程和结束线程: 2 读取和设置线程属性: 3 线程同步方式:POSIX信号量,互斥锁和条件变量 ...
- Linux 高性能服务器编程——多进程编程
问题聚焦: 进程是Linux操作系统环境的基础. 本篇讨论以下几个内容,同时也是面试经常被问到的一些问题: 1 复制进程映像的fork系统调用和替换进程映像的exec系列系统调 ...
- Linux 高性能服务器编程——高性能服务器程序框架
问题聚焦: 核心章节. 服务器一般分为如下三个主要模块:I/O处理单元(四种I/O模型,两种高效事件处理模块),逻辑单元(两种高效并发模式,有效状态机)和存储单元(不讨论). 服务器模 ...
随机推荐
- cron表达式详解(转)
Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式: (1) Seconds Minutes Hours DayofMonth Mo ...
- Java | 字符串缓冲区(StringBuilder)
为什么要出现字符缓冲区 我们都知道,String类是不可变的,但是有的时候,我们要用到字符串的拼接,如果拼接的数量小的时候,还可以,但是如果拼接的数据量太大的话,内存的占用就太大了,所以这个时候再用S ...
- 使用.net Core 3.1 多线程读取数据库
第一步:先创建一个DBhepler类,作为连接数据库中心,这个不过多说明,单纯作为数据库的连接........... 1 public static string Constr = "数据库 ...
- C语言:for语句原理及具体执行过程
#include <stdio.h> int main() { int i,s=0; for(i=1;;i*=2) { s=s+i; if(i%3==0) break; i=i+2; pr ...
- TWAIN.CPP
include "twaincpp.h" #include <QtGlobal> #include <QDateTime> #include <QSt ...
- [刘阳Java]_TortoiseSVN基础应用_第1讲
TortoiseSVN是一个免费的SVN客户端,非常好用.这里我们介绍一下TortoiseSVN基础应用. 下面的内容是转载博客园的某兄弟写的,个人觉得很不错.所以尊重转载的这篇文章,必须要给出这篇博 ...
- 【Tips】有道云笔记中Markdown插入图片
在有道云笔记中用MarkDown插入图片 新建一个文档专门用来放图片 把所有要用的图片专门放在一个笔记里,用普通模式先同步笔记,然后用分享笔记 会有一个链接,用浏览器打开这个分享的笔记就能找到所有的图 ...
- Linux安装Tomcat-Nginx-FastDFS-Redis-Solr-集群——【第十一集补充:修改fastdfs的http.conf文件进行防盗链,重启nginx失败】
1,进入fastdfs的安装目录: 2,修改http.conf文件,详情可参考: https://www.cnblogs.com/xiaolinstudy/p/9341779.html 3,重启ngi ...
- VScode中LeetCode插件无法登录的情况
VScode中LeetCode插件无法登录的情况 一直提示账户和密码无效,不知道什么问题. 后来发现是设置问题 在插件中找到leetcode 右键,点击setting 在界面里找到这里,将leetco ...
- odoo14在tree、kanban视图上添加dashboard
效果图: 实现代码:js:view的类型原来1个js给拆分成了4个: view, controller, renderer, model 1.view:AbstractView的子类,这是工厂类:类需 ...