最近在出差,要在内网做个发送自定义帧结构的数据的程序,一时间没做过这类东西,在网上学习了许多新的概念,也回顾了网络程序设计课上所学的关于网络字节序的相关知识,总结如下:
server.cpp
自定义帧结构如下:
需要用到的东西包括子系统编号,设备编号,信息类型,数据体长度,数据体
作为发送方,定义子系统编号为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 的效果,因此为开发平台无关的程序,特别要注意这点。