LabWindows網絡通訊程序例子(UDP)

UDP學習總結

1.對於UDP回調函數UDPCallback的UDP_DATAREADY事件,每次datagram達到時,都會產生回調事件("This event is received once per datagram that arrives")

2.無論使用單點發送(unicast)、多點發送(multicast)、廣播發送(broadcast),都是使用UDPWrite()函數,只是地址(destinationAddress)不同,unicast爲接收機的IP地址,multicast地址範圍224.0.0.0~239.255.255.255,broadcast地址:255.255.255.255.("When selecting a multicast address for your application to use, avoid the range 224.0.0.0 to 224.0.0.255; this range is reserved for local network administrative and maintenance purposes.")

3.對於UDPRead函數,"If you pass 0 for inputBuffer or inputBufferSize, the function peeks at the port and returns the size of the first available datagram."

4.RadioGroup控件,記得在“Edit Item(s)”中修改每一項的值。否則默認都爲0.

5.Labview軟件UDP發送字符串時,沒有發送字符串結束標誌null,若已CVI相通信,得自己手動加入字符串結束標誌位(十六進制顯示00)。

 

程序流程圖

 

//Reader


#include <udpsupp.h>
#include <ansi_c.h>
#include <cvirte.h>		
#include <userint.h>
#include "Read.h"
#define LOCAL_PORT 60100	           //定義本地UDP端口
#define MULTICAST_ADDRESS "228.0.1.1"      //多點傳播地址

static int panelHandle;
static unsigned int UDPReadHandle=0;       //UDP連接ID

int CVICALLBACK UDPReadCallBack (unsigned channel, int eventType, int errCode, void *callbackData);

int main (int argc, char *argv[])
{
	if (InitCVIRTE (0, argv, 0) == 0)
		return -1;	/* out of memory */
	if ((panelHandle = LoadPanel (0, "Read.uir", PANEL)) < 0)
		return -1;
	DisplayPanel (panelHandle);
    
	SetCtrlVal(panelHandle,PANEL_NUMERIC,LOCAL_PORT);      //顯示本地UDP端口
	SetCtrlVal(panelHandle,PANEL_STRING,MULTICAST_ADDRESS);//顯示多點傳送地址
	CreateUDPChannelConfig (LOCAL_PORT, UDP_ANY_ADDRESS, 1, UDPReadCallBack, 0,& UDPReadHandle);  //打開UDP端口
	
	RunUserInterface ();
	
	if(UDPReadHandle)
	{
	  DisposeUDPChannel (UDPReadHandle);   //關閉UDP端口
	}
	DiscardPanel (panelHandle);
	return 0;
}
//是否訂閱MULTICAST的回調函數
int CVICALLBACK SubscribMulticast (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{   int value;
	switch (event)
	{
		case EVENT_COMMIT:
			GetCtrlVal(panelHandle,PANEL_CHECKBOX,& value);   //讀取是否打鉤
			if(value)   //若打鉤,則訂閱
			{
			 UDPMulticastSubscribe (UDPReadHandle, MULTICAST_ADDRESS, NULL);
			}	
			else     //無打鉤,則退訂
			{
			 UDPMulticastUnsubscribe (UDPReadHandle, MULTICAST_ADDRESS, NULL);
			}
			
			break;
	}
	return 0;
}
//關閉面板
int CVICALLBACK panelCB (int panel, int event, void *callbackData,
		int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_CLOSE:
			QuitUserInterface(0);    
			break;
	}
	return 0;
}
//UDP接收到數據時的回調函數
int CVICALLBACK UDPReadCallBack (unsigned channel, int eventType, int errCode, void *callbackData)
{
	int size;     //datagram的大小
	char * receiveData; //接收到的數據
	int sourcePort;  
	char sourceAddress[16];
	char sourceString[16+20];  
	switch(eventType)
	{
	   case UDP_DATAREADY:
		   //If you pass 0 for inputBuffer or inputBufferSize, 
                   //the function peeks at the port and returns the size of the first available datagram

		   size = UDPRead (UDPReadHandle, 0, 0, UDP_DEFAULT_TIMEOUT, 0, 0);
		   receiveData=(char *)malloc(size*sizeof(char));
		   size = UDPRead (UDPReadHandle, receiveData, size,  UDP_DO_NOT_WAIT, & sourcePort, sourceAddress);
		   sprintf(sourceString, "[%s:%d]: ", sourceAddress, sourcePort);
		   SetCtrlVal(panelHandle,PANEL_TEXTBOX,sourceString);	   //輸出發送端的IP和端口號
		   SetCtrlVal(panelHandle,PANEL_TEXTBOX,receiveData);
		   SetCtrlVal(panelHandle,PANEL_TEXTBOX,"\n");
		   
		   free(receiveData);
		   break;
	}
	return 0;
}

//Writer

#include <ansi_c.h>
#include <udpsupp.h>
#include "radioGroup.h"
#include <cvirte.h>		
#include <userint.h>
#include "Write.h"
#define MULTICAST_ADDRESS "228.0.1.1"	 //定義多點傳播地址
//廣播發送地址爲常量UDP_LAN_BROADCAST_ADDR

static int panelHandle;
unsigned int UDPWriteHandle=0;  //UDP端口連接ID
unsigned int localPort;		    //UDP端口號

int main (int argc, char *argv[])
{
	if (InitCVIRTE (0, argv, 0) == 0)
		return -1;	/* out of memory */
	if ((panelHandle = LoadPanel (0, "Write.uir", PANEL)) < 0)
		return -1;
    Radio_ConvertFromTree (panelHandle, PANEL_RADIOGROUP);
	DisplayPanel (panelHandle);
	
	CreateUDPChannel (UDP_ANY_LOCAL_PORT, & UDPWriteHandle);  //打開UDP端口
	GetUDPAttribute (UDPWriteHandle, ATTR_UDP_PORT, & localPort);
    SetCtrlVal(panelHandle,PANEL_LOCALPORT,localPort);
	SetCtrlVal(panelHandle,PANEL_MULTICASTSTRING,MULTICAST_ADDRESS); //顯示多點傳播地址
	SetCtrlVal(panelHandle,PANEL_BROADCASTSTRING,UDP_LAN_BROADCAST_ADDR); //顯示廣播發送地址
	
	RunUserInterface ();
	//釋放UDP資源
	if(UDPWriteHandle)
	{
	   DisposeUDPChannel (UDPWriteHandle);
	}
	DiscardPanel (panelHandle);
	return 0;
}

int CVICALLBACK SendData (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{   
	unsigned int stringLen;   //待發送字符串長度
	char * sendString;		  //待發送字符串
	unsigned int destinationPort;  //遠程端口
	unsigned int radioVal;
	char address[16];      //假定輸入IP地址無誤(可以通過設置屬性“最大可輸入長度”來保證)。					 
	
	switch (event)
	{
		case EVENT_COMMIT:
			 GetCtrlAttribute (panelHandle, PANEL_TEXTBOX, ATTR_STRING_TEXT_LENGTH, & stringLen);
			 stringLen++;   //長度包括null
			 sendString=(char *)malloc(stringLen*sizeof(char));
			 GetCtrlVal(panelHandle,PANEL_TEXTBOX,sendString);		 //讀取待發送的字符串
			 GetCtrlVal(panelHandle,PANEL_DESTINATIONPORT,& destinationPort); //讀取遠程端口值
			 
			 GetCtrlVal(panelHandle,PANEL_RADIOGROUP,&radioVal);	//讀取發送方式
			 switch(radioVal)
			 {
			     case 0:	 //unicast
					 GetCtrlVal(panelHandle,PANEL_UNICASTSTRING,address);
					 break;
			     case 1:	 //multicast
					 GetCtrlVal(panelHandle,PANEL_MULTICASTSTRING,address);
					 break;
			     case 2:	 //broadcast
					 strcpy (address, UDP_LAN_BROADCAST_ADDR);
					 break;   
			 }
			 
			 UDPWrite (UDPWriteHandle, destinationPort, address, sendString, stringLen);  //向遠程端口發送數據	 
			 
			 free(sendString);
			break;
	}
	return 0;
}
//關閉面板
int CVICALLBACK panelCB (int panel, int event, void *callbackData,
		int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_CLOSE:
			QuitUserInterface(0);
			break;
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章