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模型,两种高效事件处理模块),逻辑单元(两种高效并发模式,有效状态机)和存储单元(不讨论). 服务器模 ...
随机推荐
- 从S3中拷贝或同步文件
p.p1 { margin: 0; font: 16px "Helvetica Neue"; color: rgba(53, 53, 53, 1) } p.p2 { margin: ...
- XCTF python-trade
一.查看文件类型 后缀名为pyc,说明是python字节码文件,python和java在编译方式上很像,都是编译兼并解释型,先编译成字节码,在虚拟机上解释成机器代码. 二.反编译 三.写个exp 分析 ...
- Python 的上下文管理器是怎么设计的?
花下猫语:最近,我在看 Python 3.10 版本的更新内容时,发现有一个关于上下文管理器的小更新,然后,突然发现上下文管理器的设计 PEP 竟然还没人翻译过!于是,我断断续续花了两周时间,终于把这 ...
- C语言:const详解
希望定义这样一种变量,它的值不能被改变,在整个作用域中都保持固定.例如,用一个变量来表示班级的最大人数,或者表示缓冲区的大小.为了满足这一要求,可以使用const关键字对变量加以限定:const in ...
- python之数据驱动Txt操作
一.新建数据Mail163.txt文本 二.Txt_Mail163.py脚本如下: import unittestfrom selenium import webdriverfrom selenium ...
- springboot多个service互相调用的事务处理(十三)
在一个service的方法A中,调用另一个service的方法B,方法A和方法B均存在数据库插入操作,需要添加如下配置: @Transactional(rollbackFor = Exception. ...
- BigDecimal之除不尽报错
当bigdecimal除不尽(循环小数)后会报错,下面的是BigDecimal ,divide方法提供的精确小数方法(推荐使用) BigDecimal avgCapital = loanAmount. ...
- 第三篇 -- SpringBoot打包成jar包
本篇介绍怎么将SprintBoot项目打包成jar包. 第一步:点击IDEA右侧的maven. 第二步:双击package,然后就会开始打包,当出现build success时,就打包成功了,一般在t ...
- Flask之 Marshmallow 踩坑实录
1.Marshmallow.ModelSchema 报错 AttributeError: 'Marshmallow' object has no attribute 'ModelSchema' `fr ...
- 手写RPC
服务端代码 package com.peiyu.rpcs.bios; import java.io.IOException; public interface IRpcServers { void s ...