最近在做一个实例,是用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. 【java】安全加密MessageDigest的功能及用法【hash一致性算法】

    链接地址:https://blog.csdn.net/ma1kong/article/details/2662997 1.查看MessageDigest源码的注释说明 2.和hash一致性算法 什么关 ...

  2. centos 编译 安装php

    安装phpcd /usr/local/srctar -zvxf php-5.3.10.tar.gzcd  php-5.3.10mkdir -p /usr/local/php5  #建立php安装目录. ...

  3. masm学习

    . .model flat,stdcall option casemap:none ; case sensitive ;http://www.popbook.com/wbbs/topic.asp?l_ ...

  4. 转: 微信开源C/C++ RPC框架PhxRPC

    转自: http://mp.weixin.qq.com/s?__biz=MzI4NDMyNTU2Mw==&mid=2247483734&idx=1&sn=da364812eca ...

  5. PHP中读取文件的几个方法

    整理了一下PHP中读取文件的几个方法,方便以后查阅. 1.fread string fread ( int $handle , int $length ) fread() 从 handle 指向的文件 ...

  6. 【LeetCode】Validate Binary Search Tree ——合法二叉树

    [题目] Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defin ...

  7. UNP学习笔记(第七章 套接字选项)

    有多种方法获取和设置影响套接字的选项: 1.getsockopt和setsockopt函数 2.fcntl函数 3.ioctl函数 getsockopt和setsockopt函数 这两个函数仅用于套接 ...

  8. java个人感想

    java与c++相比,摒弃了c++的指针,把c++中的stl封装成一个库,而且改变了当中的某些方法,使用方法也产生了非常多不同,读者在编程过程中须要自己细细体会 个人觉得三大框架基于前端+领域逻辑+数 ...

  9. storm - 可靠机制

    一 可靠性简单介绍                    Storm的可靠性是指Storm会告知用户每个消息单元是否在一个指定的时间(timeout)内被全然处理. 全然处理的意思是该MessageI ...

  10. 效率提升最重要的原则 - Doing one thing at a time

    前段时间流行的时间管理方法 - url=NotLrz-4f4eCgENFAECrXNw88mSLoJ2Rc2MrkP4aes1yQvPjNQRlmdYcbz9oP9U8JoBzJeY-DSUhhInx ...