Windows socket程式設計 udp協議傳送封裝自定義幀
阿新 • • 發佈:2019-01-08
最近在出差,要在內網做個傳送自定義幀結構的資料的程式,一時間沒做過這類東西,在網上學習了許多新的概念,也回顧了網路程式設計課上所學的關於網路位元組序的相關知識,總結如下:
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 的效果,因此為開發平臺無關的程式,特別要注意這點。