udp收發包

發送程序:

//udpsend.cpp

#include <netinet/in.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/ftp.h>
#include <arpa/inet.h>
#include <arpa/telnet.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>

//以下是我數據構造所依賴的頭文件
#include "MiniTipsJCE_with_header.h"
#include "video_packet.h"
#include "cs_packet2.h"    // for cs packet
#include "jce/Jce.h"

//此處是我所數據構造所依賴的命名空間
using namespace tipsPackage;

int main()
{
	char buf[4096];
	
	//buf測試數據d的構造
	tipsPackage::tipsRequest stReq;
	stReq.header.type = tipsPackage::HeartBeatRequest; //beat
	stReq.header.proto_version = 4;
	stReq.header.seq = 22222;
	stReq.client_version = "4.3";
	stReq.uin = 88888888;
	stReq.guid = "0";
	stReq.tips_key.type = KeyType_QQ;
	stReq.tips_key.value = "88888888";
	stReq.ack = "1" ;
	stReq.report = "just a test" ;
	
	//buf數據部分由自己處理構造,此處只是我的一個構造方式
	taf::JceOutputStream<taf::BufferWriter> csStreamOutput;
    stReq.writeTo(csStreamOutput);
	memcpy(buf, csStreamOutput.getBuffer(), csStreamOutput.getLength());
	
	//要發送的ip和地址
	string ip = "10.177.141.106";
	int port = 11400;
	int socket_cli = socket(AF_INET, SOCK_DGRAM, 0);
	struct sockaddr_in address;
	bzero(&address, sizeof(address));
	address.sin_family = AF_INET;
	address.sin_addr.s_addr = inet_addr(ip.c_str());
	address.sin_port = htons(port);

	//發送
	sendto(socket_cli, buf, sizeof(buf), 0, (struct sockaddr*)&address, sizeof(address));

	close(socket_cli);
	return 0;
}




接收程序:

//udprev.cpp

#include <iostream>
#include <netinet/in.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/ftp.h>
#include <arpa/inet.h>
#include <arpa/telnet.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>

// 以下是我數據構造所依賴的頭文件
#include "MiniTipsJCE_with_header.h"
#include "jce/Jce.h"
#include "video_packet.h"
#include "cs_packet2.h"    // for cs packet


using namespace std;

//此處是我所數據構造所依賴的命名空間
using namespace tipsPackage;

//輸出
void inputData(tipsBus stRespTransit)
{
	cout << "result :" << endl;
	cout << "type :" << stRespTransit.type << endl;
	cout << "sClientIp :" << stRespTransit.sClientIp << endl;
	cout << "iPort :" << stRespTransit.iPort << endl;
	cout << "header.type :" << stRespTransit.stData.header.type << endl;
	cout << "proto_version :" << stRespTransit.stData.header.proto_version << endl;
	cout << "seq :" << stRespTransit.stData.header.seq << endl;
	cout << "client_version :" << stRespTransit.stData.client_version << endl;
	cout << "uin :" << stRespTransit.stData.uin << endl;
	cout << "guid :" << stRespTransit.stData.guid << endl;
	cout << "tips_key.type :" << stRespTransit.stData.tips_key.type << endl;
	cout << "tips_key.value :" << stRespTransit.stData.tips_key.value << endl;
	cout << "ack :" << stRespTransit.stData.ack << endl;
	cout << "report :" << stRespTransit.stData.report << endl;
}

//解析數據(對數據的解析由自己構造, 這只是我自己的數據結構)
void handleData(uint8_t *buf, int bufLen)
{
	//解析buf
	CCsPacket stCsPacket;
	stCsPacket.set_packet(buf, bufLen);
	if (stCsPacket.decode() != 0)
		cout << "cs error" << endl;

	//解析cs包
	uint8_t *bufCs = (uint8_t *)stCsPacket.getBody();
	CVideoPacket stVideoPacket;
	stVideoPacket.set_packet(bufCs, stCsPacket.getBodyLen());
	if (stVideoPacket.decode() != 0)
		cout << "video error" << endl;
	
	//解析video包
	char *bufVideo = (char *)stVideoPacket.getBody().data();
	taf::JceInputStream<taf::BufferReader> csStreamInput;
	csStreamInput.setBuffer(bufVideo, stVideoPacket.getBody().length());
	
	cout << "stVideoPacket.getBody().length(): " << stVideoPacket.getBody().length() ;
	
	//解析jce
	tipsBus stRespTransit;
	stRespTransit.readFrom(csStreamInput);
	
	//輸出
	inputData(stRespTransit);
}

int main()
{
	uint8_t buf[4096]; //數據存放
	
	//要發送的ip和地址
	string ip = "10.177.141.106";
	int port = 22222;
	
	struct sockaddr_in address;
	bzero(&address, sizeof(address));
	address.sin_family = AF_INET;
	address.sin_addr.s_addr = inet_addr(ip.c_str());
	address.sin_port = htons(port);
	
	int socket_ser = socket(AF_INET, SOCK_DGRAM, 0);
	//綁定,接收此ip地址發來的數據
	bind(socket_ser, (struct sockaddr*)&address, sizeof(address)); 
	
	socklen_t add_len = sizeof(address);

	//接收
	int iRet = recvfrom(socket_ser, buf, sizeof(buf), 0, (struct sockaddr*)&address, &add_len);  

	if (iRet > 0)
	{
		//處理邏輯(如果iRet>0,則表示收到了數據,iRet爲收到的具體長度)
		handleData(buf, iRet);
	}

	close(socket_ser);
	return 0;
}

也可以採用下面這種放在一起的

//udpSendAndRev.cpp

#include <netinet/in.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/ftp.h>
#include <arpa/inet.h>
#include <arpa/telnet.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>

//以下是我數據構造所依賴的頭文件
#include "jce/Jce.h"
#include "account_inner.h"
#include "video_packet.h"
#include "cs_packet2.h"    // for cs packet

//此處是我所數據構造所依賴的命名空間
using namespace VideoAccount;

using namespace std;

//輸出
void inputData(AllocVUidRsp &stResp)
{
	cout << "result :" << endl;
	cout << "iRet :" << stResp.iRet << endl;
	cout << "lVUid :" << stResp.lVUid << endl;
}

//解析數據(對數據的解析由自己構造, 這只是我自己的數據結構)
void handleData(uint8_t *buf, int bufLen)
{
	CVideoPacket stVideoPacket;
	stVideoPacket.set_packet(buf, bufLen);
	if (stVideoPacket.decode() != 0)
		cout << "video error" << endl;
	
	//解析video包
	char *bufVideo = (char *)stVideoPacket.getBody().data();
	taf::JceInputStream<taf::BufferReader> csStreamInput;
	csStreamInput.setBuffer(bufVideo, stVideoPacket.getBody().length());
	
	cout << "stVideoPacket.getBody().length(): " << stVideoPacket.getBody().length() ;
	
	//解析jce
	AllocVUidRsp stResp;
	stResp.readFrom(csStreamInput);
	
	//輸出
	inputData(stResp);
}

int main(int argc, char *argv[])
{
	char bufSend[4096];
	char bufRev[4096];
	
	if (argc < 4)
	{
		cout << "----------------------------------------------------------------------" << endl;
		cout << "there need four argv [./udpsend sendIP sendPORT UIN]" << endl;
		cout << "like : ./udpsend 127.0.0.1 22222 569046739" << endl;
		cout << "----------------------------------------------------------------------" << endl;
		return -1;
	}
	
	string strSendIP = argv[1];
	string strSendPORT = argv[2];
	string strUIN = argv[3];
	
	//buf測試數據d的構造
	AllocVUidReq stReq;
	stReq.strOutKey = strUIN; 
	
	//buf數據部分由自己處理構造,此處只是我的一個構造方式
	taf::JceOutputStream<taf::BufferWriter> csStreamOutput;
    stReq.writeTo(csStreamOutput);
	
	//add video header
	CVideoPacket stVideoPacket;
	stVideoPacket.setBody(csStreamOutput.getBuffer(), csStreamOutput.getLength());
	stVideoPacket.setCommand(0x111);
	stVideoPacket.encode();
	
	//組裝發送數據
	memcpy(bufSend, stVideoPacket.getPacket(), stVideoPacket.getPacketLen());
	
	//要發送的ip和地址
	string ip = strSendIP;
	int port = atoi(strSendPORT.c_str());
	int socket_cli = socket(AF_INET, SOCK_DGRAM, 0);
	struct sockaddr_in address;
	bzero(&address, sizeof(address));
	address.sin_family = AF_INET;
	address.sin_addr.s_addr = inet_addr(ip.c_str());
	address.sin_port = htons(port);

	//發送
	sendto(socket_cli, bufSend, sizeof(bufSend), 0, (struct sockaddr*)&address, sizeof(address));
			
	//接收
	int iRet = recvfrom(socket_cli, bufRev, sizeof(bufRev), 0, NULL, NULL);
	
	if (iRet > 0)
	{
		//處理邏輯(如果iRet>0,則表示收到了數據,iRet爲收到的具體長度)
		handleData((uint8_t *)bufRev, iRet);
	}
	else
	{
		cout << "not recv data" << endl;
	}
	
	close(socket_cli);
	return 0;
}


收發函數:

int recvfrom(SOCKET s,void *buf,int len,unsigned int flags, struct sockaddr *from,int *fromlen);

s:標識一個已連接套接口的描述字。
buf:接收數據緩衝區。
len:緩衝區長度。
flags:調用操作方式。
from:(可選)指針,指向裝有源地址的緩衝區。
fromlen:(可選)指針,指向from緩衝區長度值。

int sendto(SOCKET s, const char * buf, int len, int flags, const struct sockaddr *to, int tolen);

   s:一個標識套接口描述字。
   buf:包含待發送數據的緩衝區。
   len:buf緩衝區中數據的長度。
   flags:調用方式標誌位。
   to:(可選)指針,指向目的套接口的地址
   tolen:to所指地址的長度。

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