(转) 在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 ...
随机推荐
- mysql赋给用户权限grant all privileges on
查看mysql用户表的结构,Field项都是各类权限限制 Host限制登录的IP,User限制登录的用户,Delete_priv限制删除权限,Grant_priv限制权限授予,Super_priv为超 ...
- Redis 在 Java 中的使用
转:http://blog.csdn.net/jiangtao_st/article/details/8256610 一.下载jar包 https://github.com/xetorthio/jed ...
- AutoCAD如何设置A0A1图纸
可以从网上下载相应的图纸模板,下载之后可以发现有相应的文字和模板文件 随后我们新建并找到这个dwt文件模板(比如要做一个A1的模板) 随后即可发现模板的样式,包括每种颜色的粗细,颜色和明细栏等 ...
- mongodb副本集的基础概念和各种机制
从一开始我们就在讲如何使用一台服务器.一个mongod服务器进程,如果只用做学习和开发,这是可以的,但如果在生产环境中,这是很危险的,如果服务器崩溃了怎么办?数据库至少要一段时间不可用,如果 ...
- 一款很实用的Memcache监控工具
装了memcahce以后想对使用情况详细了解一下,如分配的内存够不够,都存了什么,经百度后发现这款工具灰常实用!此工具来自Memcache Pecl 中 http://pecl.php.net/pac ...
- C++一元多项式相加
实验名称:一元多项式相加 // multiply.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream& ...
- c# 推荐5款超实用的.NET性能分析工具
虽然.NET框架号称永远不会发生内存泄漏,原因是引入了内存回收机制.但在实际应用中,往往我们分配了对象但没有释放指向该对象的引用,导致对象永远无法释放.最常见的情况就是给对象添加了事件处理函数,但当不 ...
- oracle session和process的关系
什么是session 通俗来讲,session 是通信双方从开始通信到通信结束期间的一个上下文(context).这个上下文是一段位于服务器端的内存:记录了本次连接的客户端机器.通过哪个应用程序.哪个 ...
- css hover对其包括的元素进行样式设置
<ul class="icon-down-single-arr-li"> <li> <a href="javascript:void(0)& ...
- c语言中结构体指针
1.指向结构体的指针变量: C 语言中->是一个总体,它是用于指向结构体,如果我们在程序中定义了一个结构体,然后声明一个指针变量指向这个结构体.那么我们要用指针取出结构体中的数据.就要用到指向运 ...