基於c語言的UDP客戶端、服務端二合一基礎程式碼

周半仙發表於2024-06-05

基於c語言的UDP客戶端、服務端二合一基礎程式碼

示意圖:
image
準備好了嗎,以下是基礎程式碼:

/**************************************************************************************************************************************
*
*   位元組序:資料以位元組流的方式進行傳輸,底層都是採用二進位制,位元組流的順序是由架構決定的,現在假設使用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;

}

相關文章