1. 程式人生 > >UDP 伺服器/客戶端

UDP 伺服器/客戶端

UDP:面向無連線,不安全,不可靠的,沒有狀態的傳輸協議
         資料報:報文傳輸(目的方要麼整個報文收,要麼都不收到)
         網路位元組序:網路採用統一的位元組順序
         htons();將埠轉換指定的順序儲存
伺服器:接受使用者的請求並作響應Server
客戶端:向用戶發出請求,並等待響應    (知道 IP與埠)

UDP:C/S
客戶端                                                                   伺服器端
1、建立套接字                                                       1、建立套接字
      int socket(協議族,轉輸方式,預設0);                  int socket(協議族,轉輸方式,預設0);
2、傳送資訊                                                           2、繫結套接字:將地址與埠
      sendto                                                                    bind
3、關閉套接字                                                       3、收/發信息                                                                                                                                                                                             recv / sendto                                                                                                                                                                                 4、關閉套接字    
地址型別:
 1、strurct sockaddr
    {
    unsigned short sa_family;//地址族
    char sa_data[14]; //地址和埠號
    };                                       struct sockaddr_in
   {
    unsigned short sa_fafily;
    unsigned short sa_port;//埠號
    struct in_addr sin_addr;/*IP地址*/
    unsigned char sin_zeron[8];//填充0(沒有意義)
   };

注:先開啟伺服器
       相關API:
      1、建立套接字
            socket
      2、繫結套接字
            bind
      3、套接字地址型別:
            struct sockaddr_in
           {
           };                                    
      4、轉換網張位元組序:
            htons(short);
            inet_addr(char* ip);
      5、接收
        recv(int ,void* ,size_t,int flag);                                                  //只接收內容                     
        recvfrom(int,void*,size_t,int flog,struct sockaddr*,int*);           //接收內容並接收IP                                                                           6、將網路位元組順序的IP地址轉換為字串(4段點分十進位制)                        char *inet_ntoa(struct in_addr in);        
            使用者層協議:雙方約定的規則
            語法             語義
            1#1             關機                                                                                                                                                                                注:在網路中,接收資訊的函式為阻塞函式(當沒有資訊來時,則阻塞。)

      

      UDP 的伺服器端程式碼實現 , 實現了客戶端傳送訊息到服務端的功能 : 

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
//伺服器i:接受訊息
int main()
{
//建立套接字--UDP
	int fd=socket(AF_INET,SOCK_DGRAM,0);
	if(fd<0)
	{
		perror("socket fail");
		return -1;
	}
//繫結套接字:用於指明套接字繫結的網絡卡和埠號
	struct sockaddr_in addr;
	//將地址結構體清空為0
	bzero(&addr,sizeof(addr));	
	addr.sin_family		=AF_INET;	//指定該地址為IPV4
	addr.sin_port		=htons(7979);//埠
	addr.sin_addr.s_addr	=inet_addr("192.168.X.XXX");//本機的網絡卡IP地址為:XXX
	if(-1==bind(fd,(struct sockaddr*)&addr,sizeof(addr)))
	{
		perror("bind");
		return -1;
	}
//3收發訊息
	char buf[100]="";
	int ilen=-1;
	while((ilen=recv(fd,buf,100,0))>0)
	{
		buf[ilen]='\0';
		printf("收到內容:%s\n",buf);
	}
//4關閉訊息
	close(fd);
}

   客戶端的程式碼實現 : 

#include<stdio.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
int main()
{
//建立套接字:
	int fd=socket(AF_INET,SOCK_DGRAM,0);
//繫結套接字:
//3傳送
	struct sockaddr_in addr;
	addr.sin_family		=AF_INET;//地址
	addr.sin_port		=htons(7979);
	addr.sin_addr.s_addr	=inet_addr("192.168.X.XXX");

        char buf[10]="";
        scanf("%s",buf);
        sendto(fd,buf,strlen(buf),0,(struct sockaddr*)&addr,sizeof(addr));
//關閉
        close(fd);
}

 

   UDP 的伺服器端程式碼實現 , 實現了客戶端傳送訊息到服務端 , 並且服務端返回訊息給客戶端 , 客戶端接收服務端訊息的功能 : 

#include<arpa/inet.h>
#include<string.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
//伺服器:接受請求,並響應請求
int main()
{
//1建立套接字:
	int fd=socket(AF_INET,SOCK_DGRAM,0);
	if(fd<0)
	{
		perror("socket fail");
		return -1;
	}
//2繫結IP地址和埠號
	struct sockaddr_in addr;
	bzero(&addr,sizeof(addr));
	addr.sin_family		=AF_INET;
	addr.sin_port		=htons(7979);
	addr.sin_addr.s_addr	=INADDR_ANY;//本機地址
	if(bind(fd,(struct sockaddr*)&addr,sizeof(addr))<0)
	{
		perror("bind fail");
		return -1;
	}
//3收訊息
	char buf[1024]="";
	int ilen=0;
	//地址型別
	struct sockaddr_in caddr;
	int addlen=sizeof(caddr);
	while(1)
	{
		//ilen=recv(fd,buf,1023,0);
		ilen=recvfrom(fd,buf,1023,0,(struct sockaddr*)&caddr,&addlen);
		if(ilen<=0)//接收失敗
			break;
		//新增結束字元
		buf[ilen]='\0';
		printf("(%s:%d):%s\n",inet_ntoa(caddr.sin_addr),\
				       caddr.sin_port,		 \
				       buf);			 \
	
		//解析字串:
		if(strcmp(buf,"1#1")==0)
		{
			printf("客戶端讓我關機\n");
			//返回狀態:
			//發關送資訊
			sendto(fd,"ok",2,0,(struct sockaddr*)&caddr,addlen);
		}
	}
//4關閉
	close(fd);
}

   客戶端的程式碼實現 : 

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
//客戶端:
int main()
{
//1建立套接字
	int fd=socket(AF_INET,SOCK_DGRAM,0);
	char buf[100]="";
//[2繫結套接字:
	int pid=fork();
	if(pid>0)//父程序---傳送資訊
	{
		//3傳送
		struct sockaddr_in addr;
		addr.sin_family		=AF_INET;//地址
		addr.sin_port		=htons(7979);
		addr.sin_addr.s_addr	=inet_addr("192.168.8.216");
		while(1)
		{
			scanf("%s",buf);//等待輸入(阻塞)
			if(sendto(fd,buf,strlen(buf),0,(struct sockaddr*)&addr,sizeof(addr))<=0)
				break;//傳送失敗
		}
		//等待子程序結束 
		wait(NULL);
	}
	else if(pid==0)//子程序---接收資訊
	{
		int ilen=0;
		while(1)
		{
			ilen=recv(fd,buf,99,0);
			if(ilen<=0)
				break;
			//新增結尾
			buf[ilen]='\0';
			printf("收到:%s\n",buf);
		}
	}
	else 
	{
		perror("fork fail");
		return -1;
	}
//4關閉
	close(fd);
}