28UDP
UDP通信流程步骤:
服务端: 等待(被动)接收发送
1: 创建 socket: socket()
2: 绑定端口: bind()
3: 读取消息: read()
4: 发送消息: write()
5: 关闭套接字: close()
客户端:主动发送接收
1: 创建 socket: socket()
2: 发送数据: write()
3: 接受结果: read()
4: 关闭套接字: close()
UDP通信流程图:

UDP通信
1.没有固定连接
2.客户端发完包,就不管了,也不知道服务端是不是收到了
UDP创建套接字、绑定套接字的方式与TCP一样,可参考TCP。
发送消息
sendto(int sockfd, void* buf, size_t len, int flags,
struct sockaddr *to, socklen_t tolen);
sockaddr由sockaddr_in转换。
UDP 没有accept创建新的通信fd,需要指定目标地址
函数可以用于TCP通信,后面两个参数会忽略
接收消息
recvfrom(int sockfd, void *buf, size_t len , int flags,
sturct sockaddr *from, socklen_t *fromlen)
UDP 没有 accept 函数来获取对端地址,这里增加了2个参数
函数可以用于TCP通信
例子:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#define SRV_PORT 8888
#define CLT_PORT 6666
void Udp_server()
{
int fd;
int iRet;
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
//创建套接字
fd = socket(PF_INET, SOCK_DGRAM, 0);
if (fd < 0)
{
perror("Fail to socket!");
return;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(SRV_PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
//绑定,可以让客户端知道通过什么IP地址和端口号来连接
iRet = bind(fd, (struct sockaddr*)&addr, addrlen);
if (iRet)
{
perror("Fail to bind!");
close(fd);
return;
}
struct sockaddr_in srcaddr;
char szBuf[1000];
char szMsg[] = "[UDP]I Received!";
while(1)
{
//接收,并获取客户端的IP和端口号(struct sockaddr*)&srcaddr
memset(szBuf, 0, 1000);
iRet = recvfrom(fd, szBuf, 1000, 0, (struct sockaddr*)&srcaddr, &addrlen);
if (iRet < 0)
{
perror("Fail to recvfrom!");
break;
}
printf("Recv:%s\n", szBuf);
//发送
fprintf(stderr,"Echo:");
scanf("%s",szMsg);
sendto(fd, szMsg, strlen(szMsg), 0, (struct sockaddr*)&srcaddr, addrlen);
}
close(fd);
return;
}
void Udp_client()
{
int fd;
int iRet;
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
fd = socket(PF_INET, SOCK_DGRAM, 0);
if (fd < 0)
{
perror("Fail to socket!");
return;
}
/*
addr.sin_family = AF_INET;
addr.sin_port = htons(CLT_PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
iRet = bind(fd, (struct sockaddr*)&addr, addrlen);
if (iRet)
{
perror("Fail to bind!");
close(fd);
return;
}
*/
struct sockaddr_in srvaddr;
char szIp[16] = ;
int port;
fprintf(stderr, "Input server IP and port:");
scanf("%s%d", szIp, &port);
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons((short)port);
srvaddr.sin_addr.s_addr = inet_addr(szIp);
char szBuf[100];
char szRcv[1000];
while(1)
{
memset(szBuf, 0, 100);
fprintf(stderr, "->");
read(STDIN_FILENO, szBuf, 100);
sendto(fd, szBuf, strlen(szBuf), 0, (struct sockaddr*)&srvaddr, addrlen);
memset(szRcv, 0, 1000);
iRet = recvfrom(fd, szRcv, 1000, 0, (struct sockaddr*)&srvaddr, &addrlen);
if (iRet < 0)
{
perror("Fail to recvfrom!");
break;
}
printf("Recv:%s\n", szRcv);
}
close(fd);
return;
}
int main(int argc, char** argv)
{
if (argc!=2
|| (strcmp(argv[1], "s") && strcmp(argv[1], "c"))
)
{
printf("Usage: %s [ c | s ]\n", argv[0]);
printf("\t s: For start udp server\n");
printf("\t c: For start udp client\n");
return 0;
}
if (argv[1][0] == 's')
{
Udp_server();
}
else if (argv[1][0] == 'c')
{
Udp_client();
}
return 0;
}
UDP打洞:

打洞就是让对方不需要通过服务器的转换,直接使用公网IP地址进行通信。
解析:
一般的主机都是使用私有IP地址(在不同的局域网中私有IP地址可以重复的),对方主机通过路由路转换成公有IP地址,再进行通信。
打洞,当主机A向某一服务器发送数据时,此时在服务器上,显示的是主机A的公网IP地址和端口号,要做的就是将该IP地址和端口号再一次返回给主机A。那么主机A就知道了自己的公网IP和端口号。此时主机B就可以直接对主机A发送数据,进而可以相互通信。
28UDP的更多相关文章
随机推荐
- JAVA 并发编程-多个线程之间共享数据(六)
多线程共享数据的方式: 1.假设每一个线程运行的代码同样.能够使用同一个Runnable对象,这个Runnable对象中有那个共享数据,比如,卖票系统就能够这么做. 2,假设每一个线程运行的代码不同. ...
- C++之函数模板
C++之函数模板与模版函数 直接上代码: C++ Code 12345678910111213141516171819202122232425262728293031323334353637383 ...
- ETL概念,ETL流程
ETL是将业务系统的数据经过抽取.清洗转换之后加载到数据仓库的过程,目的是将企业中的分散.零乱.标准不统一的数据整合到一起,为企业的决策提供分析依据. ETL是BI项目重要的一个环节. 通常情况下,在 ...
- 初始Dubbo
1. Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案.简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需 ...
- Python 正则表达式贪婪模式
贪婪模式也就是我们使用 .* 匹配任意字符时会尽可能长地向后匹配,如果我们想阻止这种贪婪模式,需要加个问号,尽可能少地匹配,如下例子: In []: import re In []: html = ' ...
- 自定义View中的Path
我们用Path可以画返回图标,可以画搜索图标,也可以画一个圆,DIDI
- 微软向开源又迈进了一大步:Checked C
导读 微软开源了 Checked C ,这是一个 C 语言的扩展版本,可以用于解决 C 语言中的一系列安全相关的隐患.正如其名字所示,Checked C 为 C 语言增加了检查,这个检查可以帮助开发者 ...
- 【黑金原创教程】【Modelsim】【第五章】仿真就是人生
声明:本文为黑金动力社区(http://www.heijin.org)原创教程,如需转载请注明出处,谢谢! 黑金动力社区2013年原创教程连载计划: http://www.cnblogs.com/al ...
- jquery如何获取type=hidden的input元素的值?
function setHiddenFields() { var hiddens = $("input:hidden"); $.each(hiddens, function (in ...
- Spoken English Practice(Don't get me wrong, that explanation makes no difference, I'm still mad at you. Come on, be reasonable!)
绿色:连读: 红色:略读: 蓝色:浊化: 橙色:弱读 下划线_为浊化 口语蜕变(2017/7/11) ...