基本套接字编程(7) -- udp篇
1. UDP概述
UDP协议全称是用户数据报协议 ,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层--传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。
与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。UDP协议的主要作用是将网络数据流量压缩成数据包的形式。一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。
2. UDP套接字编程
对于UDP套接字编程而言,服务器创建套接字后,调用bind()函数将套接字与准备接收数据的接口绑定在一起。和TCP编程不同的是,应用程序不必调用listen()和accept()函数等待客户端的连接。而只需要等待接收数据了。开发UDP套接字应用程序,有两个重要的函数sendto()和recvfrom()。服务器采用recvfrom()来接收来自客户端的数据报,并获得客户端的端地址,之后向客户端发送数据时,采用sendto()函数。
3. UDP套接字函数
3.1 消息发送函数sendto()
#include <sys/socket.h>
ssize_t sendto(int sockfd , const void *buf , size_t nbytes , int flags , const struct sockaddr *to , socklen_t addrlen);
<span style="white-space:pre"> </span>返回值:成功返回写的字节数,出错返回-1
函数说明:
sendto() 用来将数据由指定的socket传给对方主机。参数s为已建好连线的socket,如果利用UDP协议则不需经过连线操作。参数buf指向欲连线的数据内容,参数flags 一般设0,详细描述请参考send()。参数to用来指定欲传送的网络地址,结构sockaddr请参考bind()。参数addrlen为sockaddr的结构长度。
参数:
- 前三个参数sockfd , buff 和 nbytes等同于read 和 write函数的三个参数:描述符、指向写出缓冲区的指针和写字节数;
- falgs参数一般置0;
- to参数指向一个含有数据报接收者的协议地址(如IP地址和端口号)的套接字地址结构,其大小由addrlen指定;
- WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup();
- WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效;
- WSAEACESS:要求地址为广播地址,但相关标志未能正确设置;
- WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用;
- WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中;
- WSAEFAULT:buf或to参数不是用户地址空间的一部分,或to参数太小(小于sockaddr结构大小);
- WSAENETRESET:由于WINDOWS套接口实现放弃了连接,故该连接必需被复位;
- WSAENOBUFS:WINDOWS套接口实现报告一个缓冲区死锁;
- WSAENOTCONN:套接口未被连接;
- WSAENOTSOCK:描述字不是一个套接口;
- WSAEOPNOTSUPP:已设置了MSG_OOB,但套接口非SOCK_STREAM类型;
- WSAESHUTDOWN:套接口已被关闭。一个套接口以1或2的how参数调用shutdown()关闭后,无法再用sned()函数;
- WSAEWOULDBLOCK:套接口被标志为非阻塞, 但该调用会产生阻塞;
- WSAEMSGSIZE:套接口为SOCK_DGRAM类型,且数据报大于WINDOWS套接口实现所支持的最大值;
- WSAECONNABORTED:由于超时或其他原因引起虚电路的中断;
- WSAECONNRESET:虚电路被远端复位;
- WSAEADDRNOTAVAIL:所指地址无法从本地主机获得;
- WSAEAFNOSUPPORT:所指定地址族中地址无法与本套接口一切使用;
- WSAEDESADDRREQ:需要目的地址;
- WSAENETUNREACH:当前无法从本主机联上网络;
3.2 消息接收函数recvfrom()
#include <sys/socket.h>
ssize_t recvfrom(int sockfd , const void *buf , size_t nbytes , int flags , const struct sockaddr *from, socklen_t addrlen);
返回值:成功返回写的字节数,出错返回-1
函数说明:
- 前三个参数sockfd , buff 和 nbytes等同于read 和 write函数的三个参数:描述符、指向写出缓冲区的指针和写字节数;
- falgs参数一般置0;
- from参数指向一个含有数据报接收者的协议地址(如IP地址和端口号)的套接字地址结构,其大小由addrlen指定;
返回值:
- WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup();
- WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效;
- WSAEACESS:要求地址为广播地址,但相关标志未能正确设置;
- WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用;
- WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中;
- WSAEFAULT:buf或to参数不是用户地址空间的一部分,或to参数太小(小于sockaddr结构大小);
- WSAENETRESET:由于WINDOWS套接口实现放弃了连接,故该连接必需被复位;
- WSAENOBUFS:WINDOWS套接口实现报告一个缓冲区死锁;
- WSAENOTCONN:套接口未被连接;
- WSAENOTSOCK:描述字不是一个套接口;
- WSAEOPNOTSUPP:已设置了MSG_OOB,但套接口非SOCK_STREAM类型;
- WSAESHUTDOWN:套接口已被关闭。一个套接口以1或2的how参数调用shutdown()关闭后,无法再用sned()函数;
- WSAEWOULDBLOCK:套接口被标志为非阻塞, 但该调用会产生阻塞;
- WSAEMSGSIZE:套接口为SOCK_DGRAM类型,且数据报大于WINDOWS套接口实现所支持的最大值;
- WSAECONNABORTED:由于超时或其他原因引起虚电路的中断;
- WSAECONNRESET:虚电路被远端复位;
- WSAEADDRNOTAVAIL:所指地址无法从本地主机获得;
- WSAEAFNOSUPPORT:所指定地址族中地址无法与本套接口一切使用;
- WSAEDESADDRREQ:需要目的地址;
- WSAENETUNREACH:当前无法从本主机联上网络;
4. UDP回射程序实例
4.1 server.c
<pre name="code" class="cpp">#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/ip.h> const int SERV_PORT = 6000;
const int MAXLINE = 2048;
void dg_echo(int sockfd , struct sockaddr *pcliaddr , socklen_t clilen)
{
int n;
socklen_t len;
char mesg[MAXLINE];
for( ; ;)
{
len = clilen;
if((n = recvfrom(sockfd , mesg , MAXLINE , 0 , pcliaddr , &len))<0)
{
perror("recvfrom error");
exit(1);
}//if if((n = sendto(sockfd , mesg , n , 0 , pcliaddr , len)) < 0)
{
perror("sendto error");
exit(1);
}//if
}//for
}
int main(int argc , char **argv)
{
int sockfd;
struct sockaddr_in servaddr , cliaddr;
bzero(&servaddr , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
if((sockfd = socket(AF_INET , SOCK_DGRAM , 0)) < 0)
{
perror("socket error");
exit(1);
}//if if(bind(sockfd , (struct sockaddr *)&servaddr , sizeof(servaddr)))
{
perror("bind error");
exit(1);
}//if
dg_echo(sockfd , (struct sockaddr *)&cliaddr , sizeof(cliaddr));
}
4.2 client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h> const int SERV_PORT = 6000;
const int MAXLINE = 2048; void dg_cli(FILE *fp , int sockfd , const struct sockaddr *pservaddr , socklen_t servlen)
{
int n;
char sendline[MAXLINE] , recvline[MAXLINE+1]; while(fgets(sendline , MAXLINE , fp) != NULL)
{
if(sendto(sockfd , sendline , strlen(sendline) , 0 , pservaddr , servlen) < 0)
{
perror("sendto error");
exit(1);
}//if if( ( n = recvfrom(sockfd , recvline , MAXLINE , 0 , NULL , NULL)) < 0)
{
perror("recvfrom error");
exit(1);
}//if
recvline[n] = '\0';
fputs(recvline , stdout);
}//while
} int main(int argc , char **argv)
{
int sockfd , t;
struct sockaddr_in servaddr;
if(argc != 2)
{
perror("usage: udpcli <IPaddress>");
exit(1);
}//if
bzero(&servaddr , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
if((t = inet_pton(AF_INET , argv[1], &servaddr.sin_addr)) <= 0)
{
perror("inet_pton error");
<span style="white-space:pre"> </span> exit(1);
}//if if((sockfd = socket(AF_INET , SOCK_DGRAM , 0)) < 0)
{
perror("socket error");
exit(1);
}//if dg_cli(stdin , sockfd , (struct sockaddr *)&servaddr , sizeof(servaddr));
exit(0);
}
4.3 运行结果
基本套接字编程(7) -- udp篇的更多相关文章
- linux网络环境下socket套接字编程(UDP文件传输)
今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...
- 网络编程[第二篇]基于udp协议的套接字编程
udp协议下的套接字编程 一.udp是无链接的 不可靠的 而上篇的tcp协议是可靠的,会有反馈信息来确认信息交换的完成与否 基于udp协议写成的服务端与客户端,各司其职,不管对方是否接收到信息, ...
- 探索UDP套接字编程
UDP和TCP处于同一层网络模型中,也就是运输层,基于二者之上的应用有很多,常见的基于TCP的有HTTP.Telnet等,基于UDP有DNS.NFS.SNMP等.UDP是无连接,不可靠的数据协议服务, ...
- 【转】 探索UDP套接字编程
UDP和TCP处于同一层网络模型中,也就是运输层,基于二者之上的应用有很多,常见的基于TCP的有HTTP.Telnet等,基于UDP有DNS.NFS.SNMP等.UDP是无连接,不可靠的数据协议服务, ...
- 基本套接字编程(3) -- select篇
1. I/O复用 我们学习了I/o复用的基本知识,了解到目前支持I/O复用的系统调用有select.pselect.poll.epoll.而epoll技术以其独特的优势被越来越多的应用到各大企业服务器 ...
- C++网络套接字编程TCP和UDP实例
原文地址:C++网络套接字编程TCP和UDP实例作者:xiaojiangjiang 1. 创建一个简单的SOCKET编程流程如下 面向有连接的套接字编程 服务器: 1) 创建套接字(so ...
- 【Python网络编程】利用Python进行TCP、UDP套接字编程
之前实现了Java版本的TCP和UDP套接字编程的例子,于是决定结合Python的学习做一个Python版本的套接字编程实验. 流程如下: 1.一台客户机从其标准输入(键盘)读入一行字符,并通过其套接 ...
- linux网络编程-(socket套接字编程UDP传输)
今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...
- 基本套接字编程(1) -- tcp篇
1. Socket简介 Socket是进程通讯的一种方式,即调用这个网络库的一些API函数实现分布在不同主机的相关进程之间的数据交换. 几个定义: (1)IP地址:即依照TCP/IP协议分配给本地主机 ...
随机推荐
- Oracle 的递归查询将层级变成字符串
select A.PARENT_GROUP_ID, A.GROUP_ID,sys_connect_by_path(A.GROUP_ID,'/') || '/' path from dam_dataen ...
- javascript算法
代码运行环境: nodejs + mochajs /* *选择排序 *每次查找数组最小数据 *将最小数据排到左侧 */ var assert = require('assert'); describe ...
- hadoop单机
Hadoop安装教程——单机模式 博客分类: 大数据 Hadoop是MapReduce的开源实现,网上有很多相关的文章,但是很多不全,有的有点乱,本人Ubuntu小白,Hadoop初学者,根据别人的资 ...
- try it, then you know . Emacs
原来Emacs能做时间管理 http://sachachua.com/blog/2012/07/transcript-emacs-chat-john-wiegley/ http://blog.csd ...
- highchart 动态刷新(可用于制作股票时时走势)
最近项目中要求获取时时的cpu动态图,利用 highchart 可以轻松实现该功能,效果可在此地址查看:动态效果 代码如下: 页面 js 引用: <script src="你项目js的 ...
- S5PV210的电阻触摸屏&ADC控制器
一.ADC与触摸屏控制器结构框图 1.S5PV210一共支持10路模拟输入,分别为AIN0-AIN9.其中AIN0和AIN1是只做模拟输入的,AIN2-AIN9分别可以支持2个电阻式触摸屏,所以这个就 ...
- 谈谈springMVC和Strut2的理解
关于struts2框架原理 执行流程 struts2框架的核心是一个过滤器,我们编写的action类都继承ActionSupport的接口(顶层是一个过滤器filter),用户发送请求,经过核心过滤器 ...
- linux命令行下的ftp 多文件下载和目录下载
安装:yum install ftp 使用:ftp + ip (未进入ftp状态下运行) ----------------------------------------- 目标ftp服务器是一个非标 ...
- tesseract3.01的训练和使用
相关源码.资源下载:http://code.google.com/p/tesseract-ocr/downloads/list 训练步骤: 1. Generate Training Images:生 ...
- dg
package excel; import java.util.Scanner; public class doExcel { public static void main(String args[ ...