1. 程式人生 > >Windows socket程式設計 udp協議傳送封裝自定義幀

Windows socket程式設計 udp協議傳送封裝自定義幀

最近在出差,要在內網做個傳送自定義幀結構的資料的程式,一時間沒做過這類東西,在網上學習了許多新的概念,也回顧了網路程式設計課上所學的關於網路位元組序的相關知識,總結如下:

自定義幀結構如下:


需要用到的東西包括子系統編號,裝置編號,資訊型別,資料體長度,資料體

作為傳送方,定義子系統編號為10,裝置編號為1,資訊型別假設為22,資訊型別22的資料體長度為定值78

則程式碼如下:

client.cpp

// data_frame.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <string>
#include <iostream>
#include <winsock2.h>
#pragma comment(lib , "Ws2_32.lib")
using namespace std;
#pragma pack(push) //儲存對齊狀態
#pragma pack(1)
struct type_22_state_data
		{
			short a;
			short b;
			char c;
		};
struct type_22_data
	{
		short a;
		short b;
		int c;
		struct type_22_state_data d[14];	
	};//78個位元組
struct type_22
{
	char header[11];
	struct type_22_data data;
	type_22()
	{
		header[0]=10;
		header[1]=1;
		header[8]=22;
		header[9]=0;
		header[10]=78;
	}
};
#pragma pack(pop)//恢復對齊狀態
int _tmain(int argc, _TCHAR* argv[])
{
	WSADATA wsaData;

	if(WSAStartup(MAKEWORD(2,1), &wsaData))
	{ 
		printf("winsock init failed!\n");
		return 1;
	}

	struct sockaddr_in server;
	int len = sizeof(server);

	server.sin_family = AF_INET;
	server.sin_port = htons(8000);            /* 伺服器監聽埠 */
	server.sin_addr.s_addr = inet_addr("127.0.0.1");  /* 伺服器地址 */

	char buf[1024];
	struct type_22 a3;
	a3.data.a=htons(1);
	a3.data.b=htons(2);
	a3.data.c=htons(3);
	a3.data.d[0].a=htons(100);
	SOCKET sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sendto(sock_fd,(char *)&a3,sizeof(struct type_22),0,(struct sockaddr*)&server,sizeof(struct sockaddr))!=SOCKET_ERROR)
	{
		cout<<"send succeed"<<endl;
		return 0;
	}
	else
	{
		cout<<"send error"<<endl;
	}
	return 0;
}

server.cpp
#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")


#define SERVER_PORT 8000

int main()
{
	/* init winsock */
	WSADATA wsaData;

	if(WSAStartup(MAKEWORD(2,1), &wsaData))
	{ 
		printf("winsock init failed!\n");
		return 1;
	}

	struct sockaddr_in local;
	struct sockaddr_in from;
	int len = sizeof(struct sockaddr_in);

	local.sin_family = AF_INET;
	local.sin_port = htons(SERVER_PORT); /* 監聽埠 */
	local.sin_addr.s_addr = INADDR_ANY;  /* 本機 */

	/* create udp socket  */
	SOCKET sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
	bind(sock_fd, (struct sockaddr *)&local, sizeof(local));

	char bufferIn[1024];
	while(1)
	{
		bufferIn[0] = '\0';

		printf("waiting...\n");

		int nbyte=0;
		if((nbyte=recvfrom(sock_fd, bufferIn, sizeof(bufferIn), 0, (struct sockaddr *)&from, &len)) != SOCKET_ERROR)
		{
			printf("From %s:\n", inet_ntoa(from.sin_addr));
			printf("nbyte is %d",nbyte);
//			printf("header is  %d %d %d %d %d:\n",bufferIn[0],bufferIn[1],bufferIn[8],bufferIn[9],bufferIn[10]);
			for(int i=0;i<nbyte;++i)
				printf("%x ",bufferIn[i]);

		}
	}
	closesocket(sock_fd);

	WSACleanup();

	return 0;
}

執行結果如下:

客戶端為:

伺服器端為:

結果顯而易見是正確的~~注意server.cpp中htons函式的使用,是為了以網路位元組序傳遞過去,不然其中的0 0 0 64 會變成 64 0 0 0,因為x86架構的機器預設是小端法,網路位元組序是大端,因此會有64 0 0 0 的效果,因此為開發平臺無關的程式,特別要注意這點。