3:UDP中可以多次调用connect,TCP只能调用一次connect.
UDP多次调用connect有两种用途:1,指定一个新的ip&port连结. 2,断开和之前的ip&port的连结.
指定新连结,直接设置connect第二个参数即可.假设PORTa 与 PORTa'相同了(在大并发情况下会发生这种情况),那么就有可能出现A等待B的报文,却收到了C的报文.导致收报错误.解决方法内就是采用connect的UDP通信方式.在A中创建两个udp,然后分别connect到B,C.
///////////////////////////////////////////////////////////////////
对于linux网络编程,UDP协议不是面向连接的协议,直接把数据报发送到链路层,至于能不能到达目的IP和端口,它不关注;大部分时候再编写代码时候只需要在sendto函数中指定你要发送的端口和IP地址就可以了,不用绑定IP和端口。不过你是否考虑过,UDP到底是否可以进行connect,如果对UDP进行connect函数的调用,会发生什么现象呢?
在进行socket网络编程代码编写时,我个人觉得有如下三个步骤在客户端和服务端是一致的,只是触发的时机不同。
以上三个步骤在TCP协议通信中client是必须存在,但是UDP协议中,可能针对connect看到的不多。
依据上面的说明,UDP可以分为如下两种:
比较1/2两种UDP,已经连接的UDP有如下特性:
对一个UDP的套接口多次调用connect的情况如何?
第一个目的不同于TCP连接connect的使用:对于TCP连接,connect只能调用一次;针对UDP则可以connect到不同的server,eg:client需要和多个服务器同时通信。
第二个目的为了断开一个已连接的UDP连接,再次调用connect时,把套接字地址结构的地址簇成员(IPv4为sin_family,IPv6为sin6_family),设置为AF_UNSPEC即可。
具体的操作例子如下:
回显服务器
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
int sockListener,nMsgLen;
char szBuf[1024];
struct sockaddr_in addrListener;
socklen_t addrLen;
addrLen=sizeof(struct sockaddr_in);
bzero(&addrListener,sizeof(addrListener));
addrListener.sin_family=AF_INET;
addrListener.sin_port=htons(8000);
if((sockListener=socket(AF_INET,SOCK_DGRAM,0))==-1)
{
perror("error in getting a socket");
exit(1);
}
if(bind(sockListener,(struct sockaddr*)&addrListener,sizeof(addrListener))==-1)
{
perror("bind a listener for a socket");
exit(2);
}
struct sockaddr_in addrClient;
cout<<"callback server begin to listen"<0)
{
szBuf[nMsgLen]='\0';
cout<<"send back:"<
客户端1的例子
刚开始是connect,收到一个数据包后断开connect,再收到一个包后再次connect,依次.......
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
int sockClient,nMsgLen,nReady;
char szRecv[1024],szSend[1024],szMsg[1024];
struct sockaddr_in addrServer,addrClient,addrLocal;
socklen_t addrLen;
fd_set setHold,setTest;
sockClient=socket(AF_INET,SOCK_DGRAM,0);
addrLen=sizeof(struct sockaddr_in);
bzero(&addrServer,sizeof(addrServer));
addrServer.sin_family=AF_INET;
addrServer.sin_addr.s_addr=inet_addr("127.0.0.1");
addrServer.sin_port=htons(8000);
addrLocal.sin_family=AF_INET;//bind to a local port
addrLocal.sin_addr.s_addr=htonl(INADDR_ANY);
addrLocal.sin_port=htons(9000);
if(bind(sockClient,(struct sockaddr*)&addrLocal,sizeof(addrLocal))==-1)
{
perror("error in binding");
exit(2);
}
int f = 0;
if(connect(sockClient,(struct sockaddr*)&addrServer,sizeof(addrServer))==-1)
{
perror("error in connecting");
exit(1);
}
f = 1;
FD_ZERO(&setHold);
FD_SET(STDIN_FILENO,&setHold);
FD_SET(sockClient,&setHold);
cout<<"you can type in sentences any time"<
客户端2,主动向客户端1发送数据
主要是为了证明,在client1向server建立连接后,不会接受client2的数据,断开连接后会接受client2的数据
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
socklen_t addrLen=sizeof(struct sockaddr_in);
struct sockaddr_in addrServer;
char szMsg[1024];
int sockClient;
addrServer.sin_family=AF_INET;
addrServer.sin_addr.s_addr=inet_addr("127.0.0.1");
addrServer.sin_port=htons(9000);
sockClient=socket(AF_INET,SOCK_DGRAM,0);
while(true)
{
static int id=0;
snprintf(szMsg,sizeof(szMsg),"this is %d",id++);
sendto(sockClient,szMsg,strlen(szMsg),0,(struct sockaddr*)&addrServer,sizeof(addrServer));
sleep(1);
}
}