Linux下udp開發
Linux UDP開發:
UDP傳送方:(客戶端) 1、通過socket()函式實現建立套接字。 2、往sockaddr_in結構體中,填充對方的地址資訊。 3、通過bind函式,繫結自己裝置資訊(上一步的sockaddr_in結構體)。 4、通過sendto()傳送資料。 5、通過recvfrom()接收資料。
udp的建立:
int m_sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); //選擇 AF_INET 的目的就是使用 IPv4 進行通訊。 //SOCK_DGRAM (資料報套接字) //1、分組在傳送後,可能無序地到達接收端。 //2、分組可能丟失。如果發生丟失,不會採取任何補救的措施,而且接受端也不必知道有分租丟失。 //3、資料報分組有尺寸大小的限制,如果超出限制,在某些路由器和節點上就無法傳送。 //4、分組是在不建立連線的情況下被髮送到遠端程序的。 //IPPROTO_UDP建立udp的巨集。
if(m_sock < 0) { //qDebug("建立套接字失敗了"); return false; }
struct sockaddr_in m_fromAddr; memset(&m_fromAddr,0,sizeof(m_fromAddr)); m_fromAddr.sin_family=AF_INET; //IP協議家族 m_fromAddr.sin_addr.s_addr=htonl(nIpAddr); //htonl()將主機數轉換成無符號長整型的網路位元組順序 m_fromAddr.sin_port = htons(nPort);
if(bind(m_sock,(struct sockaddr*)&m_fromAddr,sizeof(m_fromAddr))<0) { close(m_sock); return false; }
DE的udp傳送:
int nSize = sizeof(struct sockaddr_in); int nLen = sendto(m_sock,sendBytes,writeNum,0,(struct sockaddr *)&sockAddr,nSize);
DE的udp接收:
法一: void UdpServerInterface::monitorInterface() { fd_set fds;//select()機制的結構集合 int len = 0; struct timeval timeout={0,250000}; //timeval結構,第一個引數秒(s),第二個引數(us),即設定250ms char buffer[2048]={0}; //2M位元組的接收緩衝區 socklen_t scokAddrLen = sizeof(struct sockaddr_in); struct sockaddr_in fromAddr;
FD_ZERO(&fds); //每次迴圈都要清空集合,否則不能檢測描述符變化 FD_SET(m_sock,&fds); //新增描述符
switch(select(m_sock+1,&fds,NULL,NULL,&timeout)) //第一個引數,是指集合中所有檔案描述符的範圍,即所有檔案描述符的最大值加1。 //這個集合中是我們要監視的檔案描述符,即我們關心資料是否可讀,如果這個集合中有一個檔案可讀,select就會返回一個大於0的值, //如果沒有可讀的檔案,則根據timeout引數再判斷是否超時,若超出timeout的時間,select返回0,若發生錯誤返回負值。 { case -1: outputMessage(QtWarningMsg,"socket select error!"); break; //select錯誤,退出程式 case 0: //outputMessage(QtWarningMsg,"socket recieve timeout!"); m_RecvArray.clear(); break; //再次輪詢 default: if (FD_ISSET(m_sock,&fds)) //測試sock是否可讀,即是否網路上有資料 { len = recvfrom(m_sock,buffer,2048,MSG_DONTWAIT, (struct sockaddr *)&fromAddr,&scokAddrLen);//接受網路資料 if (len > 0) { m_RecvArray.clear(); m_RecvArray.append(buffer,len); parserRecvMessage(m_RecvArray); } else { outputMessage(QtDebugMsg, "socket recieve error!"); } } } }
法二: { int sockfd; char buf[64]; if((sockfd = socket(AF_INET,SOCK_DGRAM,0)) == -1) { perror("socket"); exit(1); }
struct sockaddr_in myaddr,peeraddr;
memset(&myaddr,0,sizeof(myaddr)); myaddr.sin_family = AF_INET; myaddr.sin_port = htons(50000); myaddr.sin_addr.s_addr = inet_addr("192.168.1.103");
if(bind(sockfd,(struct sockaddr *)&myaddr,sizeof(myaddr)) == -1) { perror("bind"); exit(1); }
int flag; flag = fcntl(sockfd,F_GETFL); flag |= O_NONBLOCK; fcntl(sockfd,F_SETFL,flag);
int peer_len = sizeof(peeraddr); int len; while(1) { memset(buf,0,sizeof(buf)); len = recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&peeraddr,&peer_len);
if(len == -1) { if(errno == EAGAIN) { sleep(1); printf("還沒準備好呢\n"); continue; } else { perror("recvfrom"); exit(1); } }
printf("ip:%s,port:%d,buf:%s\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port),buf); } close(sockfd); return 0; }