最近在做一个实例,是用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通信中,关于客户端是否绑定的理解的更多相关文章

  1. TCP/UDP通信中server和client是如何知道对方IP地址的

    在TCP通信中 client是主动连接的一方,client对server的IP的地址提前已知的.如果是未知则是没办法通信的. server是在accpet返回的时候知道的,因为数据包中包含客户端的IP ...

  2. TCP网络协议通信原理(客户端和服务器端)

    下面直接用代码来说明TCP协议的基础知识: 服务器端代码块: from socket import * from time import ctime ''' 指定主机地址.工作端口号.接收缓存的长度 ...

  3. 网络通信协议、UDP通信、TCP通信

    网络通信协议 网络通信协议有很多种,目前应用最广泛的是TCP/IP协议,它是一个包括TCP协议和IP协议,UDP协议和其它一些协议的协议组. IP地址和端口号 目前,IP地址广泛使用的版本是IPv4, ...

  4. ACE中UDP通信

    转载于:http://www.cnblogs.com/TianFang/archive/2006/12/07/585205.html udp是一种无连接的协议,提供无连接不可靠的服务. 在ace中,通 ...

  5. Linux网络编程(四)

    在linux网络编程[1-3]中,我们编写的网络程序仅仅是为了了解网络编程的基本步骤,实际应用当中的网络程序并不会用那样的.首先,如果服务器需要处理高并发访问,通常不会使用linux网络编程(三)中那 ...

  6. 等待唤醒机制,UDP通信和TCP通信

    等待唤醒机制 通过等待唤醒机制使各个线程能有效的利用资源. 等待唤醒机制所涉及到的方法: wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中. notify():唤醒, ...

  7. .Net开发笔记(十四) 基于“泵”的UDP通信(接上篇)

    上一篇中说到了“泵”在编程中的作用以及一些具体用处,但没有实际demo,可能不好理解,这篇文章我分享一个UDP通信的demo,大概实现了类似“飞鸽传书”在局域网中文本消息和文件传输的功能.功能不全也不 ...

  8. QT之UDP通信

    前言:前一篇讲了TCP通信,这篇来看看UDP通信. 这里说明一下,UDP通信中分为三种通信分别为单播.组播和广播,下面将一一为大家介绍. 同样的我们都需要在工程文件中添加network QT += c ...

  9. Linux网络编程案例分析

    本代码来自于博主:辉夜星辰 本篇主要对运行代码中出现的问题进行分析,代码本身的内容后续展开讨论. 服务器端代码 /* Linux网络编程之TCP编程,服务器端读数据 socket函数之后,返回值ser ...

随机推荐

  1. 聊聊、Zookeeper 客户端 ZkClient

    [ZkClient]  ZkClient 是 GitHub 上一个开源的客户端,如果我们用 Maven 来管理工程,则引用如下. <dependency> <groupId>o ...

  2. django常用第三方app大全

    djangoapp 资源大全 最近经常在这个版面看到Django相关扩展的介绍,而其一个扩展写一个帖子,觉得没太必要吧. 以前整理的django资源列表,从我的wiki上转过来的. 要找django资 ...

  3. Protel中的快捷键使用(网上资源)

    使用快捷键之前,将输入法切换至中文(中国)状态 Enter——选取或启动 Esc——放弃或取消 F1——启动在线帮助窗 Tab——启动浮动图件的属性窗口 Page Up——放大窗口显示比例 Page ...

  4. Importance sampling

    用蒙特卡洛求解积分时 (Monte Carlo 随机采样对目标积分函数做近似) importance sampling func p(x) p(x)值大的地方,Monte Carlo多采几次 值小的地 ...

  5. hdu3591The trouble of Xiaoqian 多重背包+全然背包

    //给出Xiaoqian的钱币的价值和其身上有的每种钱的个数 //商家的每种钱的个数是无穷,xiaoqian一次最多付20000 //问如何付钱交易中钱币的个数最少 //Xiaoqian是多重背包 / ...

  6. android(cm11)状态栏源代码分析(一)

    (一):写在前面 近期因为工作须要,须要了解CM11中的有关于StatusBar相关的内容.总的来说,刚開始阅读其源代码的时候,是有点困难,只是通过构建相关代码的脑图和流程图,几天下来.我已经对其源代 ...

  7. Redis的安装和环境的搭建并设置服务(Redis学习笔记一)

    由于Redis在win上安装实在是太过于麻烦.我们选择把redis安装部署在linux上,然后远程连接. 安装Redis (1)cd /usr/src 进入下载目录 (1) yum install - ...

  8. JVM的GC简介和实例

    本文是一次内部分享中总结了jvm gc的分类和一些实例, 内容是introduction级别的,供初学人士参考.成文仓促,难免有些错误,如果有大牛发现,请留言,我一定及时更正,谢谢!JVM内存布局主要 ...

  9. 关于郭天祥51开发板无法烧敲代码问题的解决(Prolific USB-to-Serial Comm Port)

    1. 事件背景: 因为使用了win8系统,之前购买的郭天祥C51开发板在通过一个两头都是usb口的下载线下载程序时出现了问题:下载工具stc isp无法连接到开发板上的串口,所以无法下载程序到c51开 ...

  10. lambda表达式转换sql

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; usin ...