//socket udp 服務端
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
unsigned char szMagicNum[4];
unsigned int u32MsgIdx;
unsigned int u16MsgParamLen;
unsigned char pMsgParam[0]; // 表示不定長
} MSG_INTF_S;
// 使用不定長的結構體發送數據的關鍵在於:
// 不能在結構體中使用指針變量, 改用pMsgParam[0]這種寫法
// 因爲pMsgParam[0]不定長, 所以結構體變量要分配到堆中, 即用malloc或new來分配空間
// 接收的話, 就申請一個大一點的buffer, 一次接收完發送端發過來的不定長數據即可
// 因爲UDP的特點: UDP發一包就是一包, 要麼收到, 要麼收不到一個完整的包
int main(void)
{
//創建socket對象
int sockfd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
//創建網絡通信對象
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(9635);
//server_addr.sin_addr.s_addr = INADDR_ANY; //綁定在 0.0.0.0 地址
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//綁定在 127.0.0.1 環回地址
//綁定socket對象與通信鏈接
int ret = bind(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));
if(ret < 0)
{
printf("bind fail\n");
close(sockfd);
return -1;
}
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
MSG_INTF_S *pstRecvMsg = NULL;
MSG_INTF_S stSendMsg;
pstRecvMsg = (MSG_INTF_S *)malloc(10240);
while(1)
{
memset(pstRecvMsg, 0, 10240);
recvfrom(sockfd, pstRecvMsg, 10240, 0, (struct sockaddr*)&client_addr, &len);
printf("server: recv a connect: ip:%s, port:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
printf("server: recv szMagicNum[0] = 0x%X\n", pstRecvMsg->szMagicNum[0]);
printf("server: recv szMagicNum[1] = 0x%X\n", pstRecvMsg->szMagicNum[1]);
printf("server: recv szMagicNum[2] = 0x%X\n", pstRecvMsg->szMagicNum[2]);
printf("server: recv szMagicNum[3] = 0x%X\n", pstRecvMsg->szMagicNum[3]);
printf("server: recv u32MsgIdx = %d\n", pstRecvMsg->u32MsgIdx);
printf("server: recv u16MsgParamLen = %d\n", pstRecvMsg->u16MsgParamLen);
printf("server: recv pMsgParam = %s\n", pstRecvMsg->pMsgParam);
///////////////////////////////////////////////////////////////////////////////
// 發一個消息給客戶端
memset(&stSendMsg, 0, sizeof(MSG_INTF_S));
stSendMsg.szMagicNum[0] = 0x11;
stSendMsg.szMagicNum[1] = 0x22;
stSendMsg.szMagicNum[2] = 0x33;
stSendMsg.szMagicNum[3] = 0x44;
sendto(sockfd, &stSendMsg, sizeof(MSG_INTF_S), 0, (struct sockaddr*)&client_addr, len);
}
close(sockfd);
return 0;
}
//socket udp 客戶端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
unsigned char szMagicNum[4];
unsigned int u32MsgIdx;
unsigned int u16MsgParamLen;
unsigned char pMsgParam[0]; // 表示不定長
} MSG_INTF_S;
// 使用不定長的結構體發送數據的關鍵在於:
// 不能在結構體中使用指針變量, 改用pMsgParam[0]這種寫法
// 因爲pMsgParam[0]不定長, 所以結構體變量要分配到堆中, 即用malloc或new來分配空間
// 接收的話, 就申請一個大一點的buffer, 一次接收完發送端發過來的不定長數據即可
// 因爲UDP的特點: UDP發一包就是一包, 要麼收到, 要麼收不到一個完整的包
int main(void)
{
int buf = 0;
unsigned int cnt = 0;
//創建socket對象
int sockfd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//綁定客戶端地址信息
struct sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(9633);
//client_addr.sin_addr.s_addr = INADDR_ANY; //綁定在 0.0.0.0 地址
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//綁定在 127.0.0.1 環回地址
if(bind(sockfd, (struct sockaddr* )&client_addr, sizeof(struct sockaddr_in)) < 0)
{
printf("bind failed\n");
return -1;
}
//創建網絡通信對象
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(9635);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
socklen_t len = sizeof(server_addr);
int TotalDataLen = 0;
MSG_INTF_S *pstSendMsg = NULL;
MSG_INTF_S stRecvMsg;
while(1)
{
printf("client: input a number: ");
scanf("%d", &buf);
char *msg = (char *)"Too young too simple!!!"; // 準備不定長的數據
TotalDataLen = sizeof(MSG_INTF_S) + strlen(msg) + 1;
pstSendMsg = (MSG_INTF_S *)malloc(TotalDataLen); // 開闢一塊空間
pstSendMsg->szMagicNum[0] = 0x55;
pstSendMsg->szMagicNum[1] = 0x66;
pstSendMsg->szMagicNum[2] = 0x77;
pstSendMsg->szMagicNum[3] = 0x88;
pstSendMsg->u32MsgIdx = cnt++;
pstSendMsg->u16MsgParamLen = strlen(msg) + 1;
memcpy(pstSendMsg->pMsgParam, msg, pstSendMsg->u16MsgParamLen);
sendto(sockfd, pstSendMsg, TotalDataLen, 0, (struct sockaddr*)&server_addr, len);
if(pstSendMsg)
{
free(pstSendMsg);
pstSendMsg = NULL;
}
////////////////////////////////////////////////////////////////////////////////
// 接收服務端返回來的消息, 以此確認服務端已成功收到數據
memset(&stRecvMsg, 0, sizeof(MSG_INTF_S));
recvfrom(sockfd, &stRecvMsg, sizeof(MSG_INTF_S), 0, (struct sockaddr*)&server_addr, &len);
printf("client: recv a connect: ip:%s, port:%d\n", inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port));
if(stRecvMsg.szMagicNum[0] == 0x11 && stRecvMsg.szMagicNum[1] == 0x22
&& stRecvMsg.szMagicNum[2] == 0x33 && stRecvMsg.szMagicNum[3] == 0x44)
{
printf("client: server receive success\n\n");
}
else
{
printf("client: server reveive fail\n\n");
}
}
close(sockfd);
return 0;
}
demo運行結果:
client: input a number: 4
server: recv a connect: ip:127.0.0.1, port:9633
server: recv szMagicNum[0] = 0x55
server: recv szMagicNum[1] = 0x66
server: recv szMagicNum[2] = 0x77
server: recv szMagicNum[3] = 0x88
server: recv u32MsgIdx = 0
server: recv u16MsgParamLen = 24
server: recv pMsgParam = Too young too simple!!!
client: recv a connect: ip:127.0.0.1, port:9635
client: server receive success
client: input a number: 5
server: recv a connect: ip:127.0.0.1, port:9633
server: recv szMagicNum[0] = 0x55
server: recv szMagicNum[1] = 0x66
server: recv szMagicNum[2] = 0x77
server: recv szMagicNum[3] = 0x88
server: recv u32MsgIdx = 1
server: recv u16MsgParamLen = 24
server: recv pMsgParam = Too young too simple!!!
client: recv a connect: ip:127.0.0.1, port:9635
client: server receive success
client: input a number: 8
server: recv a connect: ip:127.0.0.1, port:9633
server: recv szMagicNum[0] = 0x55
server: recv szMagicNum[1] = 0x66
server: recv szMagicNum[2] = 0x77
server: recv szMagicNum[3] = 0x88
server: recv u32MsgIdx = 2
server: recv u16MsgParamLen = 24
server: recv pMsgParam = Too young too simple!!!
client: recv a connect: ip:127.0.0.1, port:9635
client: server receive success
client: input a number: 99
server: recv a connect: ip:127.0.0.1, port:9633
server: recv szMagicNum[0] = 0x55
server: recv szMagicNum[1] = 0x66
server: recv szMagicNum[2] = 0x77
server: recv szMagicNum[3] = 0x88
server: recv u32MsgIdx = 3
server: recv u16MsgParamLen = 24
server: recv pMsgParam = Too young too simple!!!
client: recv a connect: ip:127.0.0.1, port:9635
client: server receive success