(转) 在linux网络UDP通信中,关于客户端是否绑定的理解
最近在做一个实例,是用RTSP协议完成。服务器已经有了,只需要把客户端做好就行了,在做的过程中发现了一些问题,就是关于UDP客户端是否绑定的问题。
也许大家在书上看到的大多都是说UDP客户端不需要绑定,直接就可以和服务器通信,一开始我也是这样认为的,而且我也是这样做的,可是做着做着发现出现了问题。
在UDP通信中,我们建立一个服务器,进行绑定,等待客户端的连接请求,现把服务器的代码贴出来简述:
///////////*****************************server.c********************************************////////////////////////////////////
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BUF_SIZE 1024
#define port 8090
int main()
{
char buf[BUF_SIZE],buf1[BUF_SIZE];
int fd,n,len;
char buf2[20]="server:\n";
struct sockaddr_in serv,serfrom;
if((fd=socket(AF_INET,SOCK_DGRAM,0)<0))
{
printf("sock err\n");
exit(1);
}
printf("sock ok\n");
serv.sin_family=AF_INET;
serv.sin_addr.s_addr=INADDR_ANY;
serv.sin_port=htons(port);
if(bind(fd,(struct sockaddr*)&serv,sizeof(serv))<0)
{
printf("bind err\n");
exit(1);
}
len=sizeof(serfrom);
while(1)
{
n=recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr*)&serfrom,&len);
if(n<0)
{
printf("recv err\n");
exit(1);
}
buf[n]='\0';
printf("%s\n",buf);
if(strncmp(buf,"bye",3)==0)
{
break;
}
else
{
printf("input:\n");
scanf("%s",buf1);
strcat(buf2,buf1);
sendto(fd,buf2,sizeof(buf2),0,(struct sockaddr*)&serfrom,len);
memset(buf2+10,0,sizeof(buf2+10));
}
}
close(fd);
return 0;
}
///////////////////*************************client.c**********************************///////////////////////////////////
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BUF_SIZE 1024
#define port 8090
int main(int argc,char *argv[])
{
char buf[BUF_SIZE],buf1[BUF_SIZE],buf2[BUF_SIZE];
int fd,n,len;
struct sockaddr_in serfrom;
if((fd=socket(AF_INET,SOCK_DGRAM,0)<0))
{
printf("sock err\n");
exit(1);
}
printf("sock ok\n");
bzero(&serfrom,sizeof(serfrom));
serfrom.sin_family=AF_INET;
if(inet_pton(AF_INET,argv[1],&serfrom.sin_addr)<0)
{
printf("inet err\n");
exit(1);
}
serfrom.sin_port=htons(port);
bzero(&(serfrom.sin_zero),8);
len=sizeof(serfrom);
while(1)
{
printf("input:\n");
scanf("%s",buf1);
n=sendto(fd,buf1,sizeof(buf1),0,(struct sockaddr*)&serfrom,len);
if(n<0)
{
printf("send err\n");
exit(1);
}
else
{
n=recvfrom(fd,buf2,sizeof(buf2),0,(struct sockaddr*)&serfrom,&len);
buf[n]='\0';
printf("%s\n",buf2);
}
}
close(fd);
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
上面是UDP服务器和客户端的代码,可以看到在客户端没有绑定,在服务器端绑定了,为什么客户端没有绑定,而服务器却能给客户端发送数据呢? 问题的关键就在客户端的sendto()函数,n=sendto(fd,buf1,sizeof(buf1),0,(struct sockaddr*)&serfrom,len),,在他的第五个参数struct sockaddr中,(sendto中,serfrom中里应该有目的的ip及端口)。在客户端么有给服务器发送数据之前,服务器是不知到它的存在的,在这里我没有给他绑定,但是在这背后,系统已经做了一些绑定的操作。系统在当前系统中找一个没有被占用的端口给它,然后进行绑定,这样客户端在进行sendto()后,在服务器上有n=recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr*)&serfrom,&len);,(recvfrom中,serfrom中里应该有数据源的ip及端口号),会把客户端的ip地址和系统选择的端口号填入这个struct sockaddr结构体中(即serfrom中),这样服务器就知道了客户端的存在,包括它的ip即端口号。这样他们就可以进行通信了。但是这是在客户端先给服务器发送信息的情况下(即客户端先sendto,然后服务器recvfrom)。如果客户端一开始就不给服务器发送消息,客户端的功能只是从服务器接收消息呢??? 这时服务器就不知道客户端的ip及端口号了,这样它们应该怎么样通信呢???这也是我在这个项目中遇到的问题。在rtsp通信中,先建立的是TCP和服务器进行连接,然后用两个UDP端口来接受服务器的数据,当TCP的连接完成后就关闭了,而UDP还要接受数据,这时相当于真正的UDP通信了,然而这时客户端不在给服务器发送数据了(就像刚才上面的情况),这样的话,服务器怎么样知道发给哪个客户端呢? 只有对客户端进行绑定了。我把上述的代码进行了改变,
/////////////////////////************************server.c************************/////////////////////////////////////
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BUF_SIZE 1024
#define port 8090
int main()
{
char buf[BUF_SIZE],buf1[BUF_SIZE];
int fd,n,len,i=0;
char buf2[20]="server:\n";
struct sockaddr_in serv,serfrom;
if((fd=socket(AF_INET,SOCK_DGRAM,0))<0)
{
printf("sock err\n");
exit(1);
}
printf("sock ok\n");
bzero(&serv,sizeof(serv));
serv.sin_family=AF_INET;
serv.sin_addr.s_addr=INADDR_ANY;
serv.sin_port=htons(port);
bzero(&serv.sin_zero,8);
bzero(&serfrom,sizeof(serfrom));
serfrom.sin_family=AF_INET;
serfrom.sin_port=htons(4681);
serfrom.sin_addr.s_addr=INADDR_ANY;
bzero(&serfrom.sin_zero,8);
if(bind(fd,(struct sockaddr*)&serv,sizeof(serv))<0)
{
printf("bind err\n");
exit(1);
}
len=sizeof(serfrom);
while(1)
{
sendto(fd,buf2,sizeof(buf2),0,(struct sockaddr*)&serfrom,len);
sleep(0.1);
}
close(fd);
return 0;
}
上面的代码中,服务器不接受数据只给客户端发送数据,发送的目的ip及端口在serfrom中,ip地址采用默认,端口号为4681,就是说服务器向这个ip的4681端口发送数据,然后看看下面客户端的代码:
////////////////////////////////////////***********************server.c***************************///////////////////////////////////////////////////////////////////
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BUF_SIZE 1024
#define port 4681
int main(int argc,char *argv[])
{
char buf[BUF_SIZE],buf1[BUF_SIZE],buf2[BUF_SIZE];
int fd,n,len;
struct sockaddr_in serfrom,self;
if((fd=socket(AF_INET,SOCK_DGRAM,0))<0)
{
printf("sock err\n");
exit(1);
}
printf("sock ok\n");
len=sizeof(self);
bzero(&serfrom,sizeof(serfrom));
serfrom.sin_family=AF_INET;
serfrom.sin_addr.s_addr=INADDR_ANY;
serfrom.sin_port=htons(port);
bzero(&(serfrom.sin_zero),8);
if(bind(fd,(struct sockaddr*)&serfrom,sizeof(serfrom))<0)
{
printf("bind err\n");
exit(1);
}
while(1)
{
n=recvfrom(fd,buf2,sizeof(buf2),0,(struct sockaddr*)&serfrom,&len);
buf[n]='\0';
printf("%s\n",buf2);
}
close(fd);
return 0;
}
我把客户端绑定带端口4681上,只要服务器有数据发送,客户端就能接受,但是这样只能处理定点的客户端。
在RTSP中,我们在SETUP命令中指明了客户端的接受端口,当客户端通过TCP给服务器发送PLAY命令后,服务器就开始向我们在SETUP中指定的端口发送数据,我们只要把客户端绑定在这些端口上,就能接受到服务器发送的数据了。所以,在UDP中,什么时候绑定,什么时候不需要绑定,我们要看情况而定,因为对于RTSP中的后期,客户端不在给服务器发送数据,只有让服务器向指定的端口发,然后我们把客户端绑定在那里,这样就可以了。。。。OK,我也该睡觉了,,
参考:
1,在linux网络UDP通信中,关于客户端是否绑定的理解
http://blog.csdn.net/chenyu123123/article/details/8518642
(转) 在linux网络UDP通信中,关于客户端是否绑定的理解的更多相关文章
- TCP/UDP通信中server和client是如何知道对方IP地址的
在TCP通信中 client是主动连接的一方,client对server的IP的地址提前已知的.如果是未知则是没办法通信的. server是在accpet返回的时候知道的,因为数据包中包含客户端的IP ...
- TCP网络协议通信原理(客户端和服务器端)
下面直接用代码来说明TCP协议的基础知识: 服务器端代码块: from socket import * from time import ctime ''' 指定主机地址.工作端口号.接收缓存的长度 ...
- 网络通信协议、UDP通信、TCP通信
网络通信协议 网络通信协议有很多种,目前应用最广泛的是TCP/IP协议,它是一个包括TCP协议和IP协议,UDP协议和其它一些协议的协议组. IP地址和端口号 目前,IP地址广泛使用的版本是IPv4, ...
- ACE中UDP通信
转载于:http://www.cnblogs.com/TianFang/archive/2006/12/07/585205.html udp是一种无连接的协议,提供无连接不可靠的服务. 在ace中,通 ...
- Linux网络编程(四)
在linux网络编程[1-3]中,我们编写的网络程序仅仅是为了了解网络编程的基本步骤,实际应用当中的网络程序并不会用那样的.首先,如果服务器需要处理高并发访问,通常不会使用linux网络编程(三)中那 ...
- 等待唤醒机制,UDP通信和TCP通信
等待唤醒机制 通过等待唤醒机制使各个线程能有效的利用资源. 等待唤醒机制所涉及到的方法: wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中. notify():唤醒, ...
- .Net开发笔记(十四) 基于“泵”的UDP通信(接上篇)
上一篇中说到了“泵”在编程中的作用以及一些具体用处,但没有实际demo,可能不好理解,这篇文章我分享一个UDP通信的demo,大概实现了类似“飞鸽传书”在局域网中文本消息和文件传输的功能.功能不全也不 ...
- QT之UDP通信
前言:前一篇讲了TCP通信,这篇来看看UDP通信. 这里说明一下,UDP通信中分为三种通信分别为单播.组播和广播,下面将一一为大家介绍. 同样的我们都需要在工程文件中添加network QT += c ...
- Linux网络编程案例分析
本代码来自于博主:辉夜星辰 本篇主要对运行代码中出现的问题进行分析,代码本身的内容后续展开讨论. 服务器端代码 /* Linux网络编程之TCP编程,服务器端读数据 socket函数之后,返回值ser ...
随机推荐
- mac xampp命令行调用mysql
参考 http://www.cnblogs.com/machao/p/6206483.html 直接mysql不行,显示command not found 调用 sudo ln -s /applica ...
- (转)python装饰器二
Python装饰器进阶之二 保存被装饰方法的元数据 什么是方法的元数据 举个栗子 def hello(): print('Hello, World.') print(dir(hello)) 结果如下: ...
- JAVA Eclipse开发Android如何让超出界面的部分自动显示滚动条
在原有布局的最外围添加一层ScrollView,注意原有布局的声明也要删了 <ScrollView xmlns:android="http://schemas.android.com/ ...
- 有问必答项目 -数据库设计文档(ask-utf-8)
有问必答项目 -数据库设计文档(ask-utf-8) 表前缀的使用 早期租用公共的服务器 一个数据库,保存多个项目(问答.电子商务.医院),为了区分这些项目,使用前缀分割 ask_ ec_ hospi ...
- apue学习笔记(第十一章 线程)
本章将进一步深入理解进程,了解如何使用多个控制线程(简单得说就是线程)在单进程环境中执行多个任务. 线程概念 每个线程都包含有表示执行环境所必须的信息:线程ID.一组寄存器值.栈.调度优先级和策略.信 ...
- vector(可变数组) 用于UDP通信
头文件: #include<vector.h> 然后,声明并初始化vctor数组. vector<char> str(len); 其中len可以是变量或者常量.(其实用常量就 ...
- swiper的理解
参考:Swiper中文网 Swiper使用方法: <!DOCTYPE html> <html> <head> <meta charset="UTF- ...
- 【Android】getActionBar()为null的解决方法总结
前言 在使用 ActionBar的时候,有时候会爆出空指针异常,这是由于应用没有获取到 ActionBar 导致的,而导致应用没有获取到 ActionBar 的原因比較多.所以我们以下就来总结一下 A ...
- 取出所有的Map集合
public static void main(String[] args) { Map<Integer, String> map = new HashMap<Integer, St ...
- client交互技术简单介绍
随着网络应用的不断丰富,client交互技术也如雨后春笋一般,遍地开花. 正是这些技术的支持,我们的互联网世界变得更加丰富多彩.一个浏览器上.不用说是简单的动画效果,就是一个Office应用也能顺畅的 ...