Linux学习四:UDP编程(上)
关于UDP和TCP对比优缺,这里就不说了。
使用UDP代码所掉用的函数和用于TCP的函数非常类似,这主要因为套接口库在底层的TCP和UDP的函数上加了一层抽象,通过这层抽象使得编程更容易,但失去了一些控制。
二者函数调用唯一的实际区别是soceket函数调用的一个参数,TCP的是SOCK_STREAM,UDP的是SOCK_DGRAM,二者都可以使用recvfrom函数,而recv只用于TCP。
当然函数的变化不是这么简单,因为你要从一种有连接的协议转向到无连接的协议上去。
这里写个很简单直接的UDP应用了解过程。实现一个启动向另一个系统的某个端口传输消息的程序,这个程序没有握手机制,也不确定另一个系统是否正在侦听、接受或处理数据。
发送端:sender,发送文本消息,再发个终止消息(告诉接收方发送完毕)。
UDP编程的客户端一般步骤是:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt();* 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选
4、设置对方的IP地址和端口等属性;
5、发送数据,用函数sendto();
6、关闭网络连接;
sender.c :
#include “stdio.h”只能用“”表示了,<显示不出来
#include “stdlib.h”
#include “string.h”
#include “sys/socket.h”
#include “netinet/in.h”
#include “arpa/inet.h”
#include “netdb.h”
int port=6789;
void main()
{
int socket_descriptor;// 定义套接口描述字
int i=0;
char buf[120];//设置缓冲区
struct sockaddr_in address;//处理网络通信地址,把像xxx.xxx.xxx.xxx十进制
//的IP地址转化 为32位整数,失败返回INADDR_NONE
初始化Internet协议套接字地址结构
bzero(&address,sizeof(address));//空数据结构
address.sin_family=AF_INET;
address.sin_addr.s_addr=inet_addr("127.0.0.1");//设置服务器的ip地址函数
address.sin_port=htons(port); //设置端口
创建一个UDP套接字
socket_descriptor=socket(AF_INET,SOCK_SGRAM,0);
循环发送数据
for(i=0;i<120;i++)
{
sprintf(buf,"data packet with ID %d\n",i);
sendto(socket_descriptor,buf,sizeof(buf),0,
(struct sockaddr *)&address,sizeof(address));
}
发送一个终止信息
sprintf(buf,"stop\n");
sendto(socket_descriptor,buf,sizeof(buf),0,
(struct sockaddr *)&address,sizeof(address));
关闭网络
close(socket_descriptor);
printf("Message Sent,Terminating\n");
exit(0);
}
具体详细注释下:
首先库文件:
stdlib.h:包含了C、C++语言的最常用的系统函数,定义了五种类型、一些宏和通用工具函数.
常用的函数如malloc()、calloc()、realloc()、free()、ystem()、atoi()、atol()、rand()、
srand()、exit()等等
string.h:字符数组的函数定义的头文件,常用函数有strlen、strcmp、strcpy等等
sys/socket.h:提供socket函数及数据结构
netinet/in.h:定义数据结构sockaddr_in,互联网地址族
arpa/inet.h:提供IP地址转换函数
netdb.h:提供设置及获取域名的函数
再看看涉及到的函数:
struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,
二者长度一样都是16个字节。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。一般情况下,
需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中。
inet_addr被linux下的inet_aton取代.函数作用是把作为参数的字符串转化为内部能够使用的一个
作为因特网地址的整数.
htons函数处理不同系统对内部的数据表示方法不同,使你的主机字节序和网络字节序匹配.
socket函数创建套接字:0表示默认 socket函数,向系统申请一个通信端口SOCK_DGRAM 默认使用UDP
调用socket函数时:
UDP使用SOCK_SGRAM,
TCPIP使用SOCK_STREAMA
AF_INET表示IPV4.
AF_INET6表示IPV6
AF_UNIX,AF_LOCAL表示本地通信
SOCK_STREAM: 提供面向连接的稳定数据传输,即TCP协议。
OOB: 在所有数据传送前必须使用connect()来建立连接状态。
SOCK_DGRAM: 使用不连续不可靠的数据包连接。
SOCK_SEQPACKET: 提供连续可靠的数据包连接。
SOCK_RAW: 提供原始网络协议存取。
SOCK_RDM: 提供可靠的数据包连接。
SOCK_PACKET: 与网络驱动程序直接通信。
sendto函数通过套接口发送一个消息,在此使用了无连接的套接口:消息的发送目的地址由address指定。具体参数介绍不再说明。
sprintf函数把格式化的数据写入某个字符串,返回值:字符串长度(strlen)例如:
char* who = "I";
char* whom = "csdn";
sprintf(s, "%s love %s.", who, whom); //产生:"I love csdn. " 这字符串写到s中
接收端:receiver
receiver.c:
#include “stdio.h”只能用“”表示了,<显示不出来
#include “stdlib.h”
#include “string.h”
#include “sys/socket.h”
#include “netinet/in.h”
#include “arpa/inet.h”
#include “netdb.h”
int port=6789;
void main()
{
int sin_len;
char message[256];
int socket_descriptor;
struct sockaddr_in sin;
printf("Waiting for data from sender\n");
bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=htonl(INADDR_ANY);//htonl(将32位主机字符顺序
//转换成网络字符顺序)
sin.sin_port=htons(port);//htons(将16位主机字符顺序转换成网络字符
//顺 序)
sin_len=sizeof(sin);
socket_descriptor=socket(AF_INET,SOCK_DGRAM,0);//建立一个端口
bind(socket_descriptor,(struct sockaddr *)&sin,sizeof(sin));//将主机地址
//与端口绑定
while(1)
{
recvfrom(socket_descriptor,message,sizeof(message),0,
(struct sockaddr *)&sin,&sin_len);//接受消息
printf("Response from server:%s\n",message);
if(strnmcp(message,"stop",4)==0)//比较接受message和stop的前4个
//字符。>返回大于1,=返回0。
{
printf("Sender has told me end connection\n");
break;
}
}
close(socket_descriptor);
exit(0);
}
分别:gcc -o xxx xxx.c 注意:o是小写,大写的话会提示没有xxx文件或文件夹。
然后分别在不同工作台运行:./xxx
显示如下:
Linux学习四:UDP编程(上)的更多相关文章
- Linux学习之socket编程(二)
Linux学习之socket编程(二) 1.C/S模型——UDP UDP处理模型 由于UDP不需要维护连接,程序逻辑简单了很多,但是UDP协议是不可靠的,实际上有很多保证通讯可靠性的机制需要在应用层实 ...
- 基于Linux下的UDP编程
一. Linux下UDP编程框架 使用UDP进行程序设计可以分为客户端和服务器端两部分. 1.服务器端程序包括: Ø 建立套接字 Ø 将套接字地址结构进行绑定 Ø 读写数据 Ø 关闭套接字 2 ...
- Linux学习之socket编程(一)
socket编程 socket的概念: 在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程,“IP地址+端口号”就称为socket. 在TCP协议中,建立连接的两个进 ...
- Linux学习之Shell编程基础
转自:http://my.oschina.net/itblog/blog/204410 1 语法基本介绍1.1 开头 程序必须以下面的行开始(必须方在文件的第一行): #!/bin/sh 符号#!用来 ...
- Linux 学习 (四) 帮助命令
Linux达人养成计划 I 学习笔记 man 命令 获取指定命令的帮助 man的级别 1:查看命令的帮助 2:查看可被内核调用的函数的帮助 3:查看函数和函数库的帮助 4:查看特殊文件的帮助(主要是/ ...
- linux学习总结----shell编程
## 环境变量 ## 全局变量 ``` 常见的全局环境变量 PATH 指令的搜索路径 HOME 用户的家目录 LOGNAME 登录名 SHELL 脚本的类型 使用全局环境变量 echo $PATH 自 ...
- linux学习四x系统指令
一.任务调度 任务调度:系统在某个时间执行特定的命令或者程序 如: 1.对于一些需要周期性执行的一些系统指令 2.定期的病毒扫描 3.定期数据库备份等 命令:crontab 设置任务调度文件: / ...
- Linux学习 -->解决Ubuntu系统上 No command 'crond' found
前两天,准备在Ubuntu服务器上,定时执行Gitlab备份的命令,如下所示 编辑 vi /etc/crontab 文件,添加如下定时脚本 # edited by ouyang 2017-8-11 添 ...
- Linux学习(四)-Linux常用命令
1.运行级别类 1.1运行级别说明: 0:关机 1:单用户[可用于找回丢失密码] 2:多用户状态没有网络服务 3:多用户状态有网络服务 4:系统未使用保留给用户 5:图形界面 6:系统重启 常用运行级 ...
随机推荐
- mysql 完整性约束
mysql 完整性约束 数据的完整性概述根据完整性实施的方法将完整性约束分为四类:1.实体完整性 实体完整性的实现:通过在表中设置主键约束.唯一约束或标识列来实现 主键约束:应用于表列的一个约束 用法 ...
- android中加载的html获取的宽高不正确
wap页面使用 js库是zepto,按照惯例在$(function(){})中,来获取当前可视区的宽高,但得到的宽高却与预想的相差十万八千里. 原本android手机的浏览器设定的宽高基本是360*6 ...
- oracle 报警日志详解
oracle报警日志是一个非常重要的日志,其有两种实现方法: 1.通过全局表来实现,这种方法有一种缺点,就是在关闭数据库后或者数据库宕机后就不能在使用了 2.通过外部表来实现,这种方法避免了方法一种的 ...
- 【我是老中医】Win10系统下MATLAB无法正常打开的解决方案
转眼大四了,要开始做毕设了,导师给的题目要用到他之前做的东西,都是MATLAB做的,所以不太熟悉MATLAB的我也得用这玩意儿了,想想自己目前也就大二的DSS实验和大三的AI实验用过MATLAB,当时 ...
- 模板方法模式(Template Method Pattern)
模板方法模式是一种基于继承的代码复用技术,定义一个操作中的算法的骨架,而将步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤. 模式中的角色 抽象类(Abstrac ...
- 【性能诊断】StackOverflow引发的“网络”及系统稳定性问题
背景描述: 最近一个项目的系统管理员和业务运维人员分别反馈问题: 1.应用系统每个月会有一两次宕机,需要管理员手工重启IIS: 2.财务模块一个功能经常报网络错误“网络异常,请检查网络连接”“Unab ...
- 用RollViewPager实现Android滚动banner
最近项目中要实现一个循环滚动的banner,效果如下图 这个自己写实在是不方便,而且写出来也很难保证没有bug和性能缺陷,好在网上有人开源了一个实现滚动banner的RollViewPager框架,亲 ...
- AlwaysOn添加高可用性自定义登陆用户的方法
1.在主服务器添加自定义登陆用户,比如TestUser 2.在主服务器执行如下SQL,在master数据库创建存储过程sp_hexadecimal,sp_help_revlogin USE maste ...
- [Andriod] - Andriod Studio + 逍遥模拟器
Andriod Studio自身自带的模拟器实在太卡,用Genymotion模拟器又要安装VirtualBox,然后一堆的设置,结果还是卡B. 网上下了个逍遥模拟器,这模拟器是游戏专用的,目前正式版的 ...
- 事件驱动之Twsited异步网络框架
在这之前先了解下什么是事件驱动编程 传统的编程是如下线性模式的: 开始--->代码块A--->代码块B--->代码块C--->代码块D--->......--->结 ...