基于c语言的UDP客户端、服务端二合一基础代码
示意图:
准备好了吗,以下是基础代码:
/**************************************************************************************************************************************
*
* 字节序:数据以字节流的方式进行传输,底层都是采用二进制,字节流的顺序是由架构决定的,现在假设使用X86架构,是采用小端存储
* 网络字节序:
* 本地字节序:
*
* 大端存储:低地址存储高字节 当数据超过1个字节的时候才需要区分大端还是小端 假设int型 0x12345678 0x12 | 0x34 | 0x56 | 0x78
* 小端存储:低地址存储低字节 当数据超过1个字节的时候才需要区分大端还是小端 假设int型 0x12345678 0x78 | 0x56 | 0x34 | 0x12
*
* 设备A采用X86架构,所以设备A采用小端存储 待发送的数据 :0x12345678
* 设备B采用ARM架构,所以设备B采用大端存储 待接收的数据 :?
*
* 为了统一发送数据的格式,所以互联网传输的数据统一采用大端方式,为了方便开发,linux系统提供了转换的接口:htonl、htons、ntohl、ntohs
*
* h :host 主机/本地
* to: 转换
* n :net 网络
* l :long 长整型
* s :short 短整型
*
* htons:把本地字节序的一个短整型转换为网络字节序
* htonl:把本地字节序的一个长整型转换为网络字节序
* ntohs:把网络字节序的一个短整型转换为本地字节序
* ntohl:把网络字节序的一个长整型转换为本地字节序
* ***********************************************************************************************************************************/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <time.h>
#include <pthread.h>
#define MULTICAST_ADDR "224.88.88.88"
//这里的宏定义是你自定义的广播组,如同聊天室需要在同一个频道
int udp_socket;
//客户端任务
void *client(void *arg)
{
//2.向目标主机发送消息,需要设置目标端口和目标地址
char buffer[128] = {0};
struct sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET; //协议族,是固定的
dest_addr.sin_port = htons(9999); //服务器端口,必须转换为网络字节序
dest_addr.sin_addr.s_addr = inet_addr(MULTICAST_ADDR); //服务器地址 "192.168.64.xxx"
bind(udp_socket,(struct sockaddr *)&dest_addr, sizeof(dest_addr));//绑定服务器和端口
while(1)
{
printf("请输入内容:");
scanf("%s",buffer);
//3.发送客户端的上线时间
sendto(udp_socket,buffer,strlen(buffer),0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
}
}
int main(int argc,char *argv[])
{
//检查参数有效性
if (argc != 2)
{
fprintf(stderr, "argument is invaild ,errno:%d,%s\n",errno,strerror(errno));
exit(1);
}
//1.创建UDP套接字
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_socket == -1)
{
fprintf(stderr, "udp socket error,errno:%d,%s\n",errno,strerror(errno));
exit(1);
}
// 启用广播选项
//setsockopt(udp_socket, SOL_SOCKET, SO_BROADCAST, &broadcast, option_len);
//getsockopt(udp_socket, SOL_SOCKET, SO_BROADCAST,(void *)&optval, &option_len);
//----------------------------------------------------------------------------------------
//2.需要先绑定服务器的端口和地址
struct sockaddr_in host_addr;
struct ip_mreqn mreq;
host_addr.sin_family = AF_INET; //协议族,是固定的
host_addr.sin_port = htons(atoi(argv[1])); //目标端口,必须转换为网络字节序
host_addr.sin_addr.s_addr = INADDR_ANY; //目标地址 "192.168.64.xxx" 已经转换为网络字节序 INADDR_ANY
bind(udp_socket,(struct sockaddr *)&host_addr, sizeof(host_addr));
//----------------------------------------------------------------------------------------
//加入多播组
mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_ADDR);
mreq.imr_address.s_addr= htonl(INADDR_ANY); // 或者指定网络接口地址
mreq.imr_ifindex = 0;
setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
//----------------------------------------------------------------------------------------
//创建客户端线程
pthread_t hostser;
pthread_create(&hostser,NULL,client,NULL);
//3.调用recvfrom等待接收数据,并且接收客户端的网络信息
char buf[128] = {0};
struct sockaddr_in client;
socklen_t client_len = sizeof(client);
while(1)
{
recvfrom(udp_socket,buf,sizeof(buf), 0 ,(struct sockaddr *) &client,&client_len); //默认会阻塞
// 输出消息内容
time_t now = time(NULL);
printf("client ip is [%s] time:%s %s\n", inet_ntoa(client.sin_addr), ctime(&now),buf);
bzero(buf,sizeof(buf));
}
return 0;
}
标签:UDP,字节,二合一,udp,client,socket,include,服务端,addr
From: https://www.cnblogs.com/zcx0326/p/18233701