1. 程式人生 > >UDP型別的C/S簡單例項

UDP型別的C/S簡單例項

與TCP型別的C/S相比較,UDP缺少了connetc(),listen(),acept()函式,這是用於UDP協議無連線的特性,不用維護TCP的連線,斷開狀態

伺服器端大體的流程為建立套接字,套接字與地址結構進行繫結,收發資料,關閉套接字,分別對應於函式socket(),bind(),sendto()

recvfrom()和close

先建立套接字檔案描述符,使用函式socket(),生成套接字描述符

#include<sys/types.h>
#include<sys/socket.h>
int socket(int domain,int type,int protocol);

使用者呼叫socket函式,然後這個函式呼叫系統呼叫函式sys_socket(),系統呼叫sys_socket()分為兩部分,一部分生成核心socket結構,另一部分與檔案描述符進行繫結,將繫結的檔案描述符返回。

所以我們可以通過訪問套接字描述符的方式去和核心空間互動

然後第二步就是將套接字描述符與一個地址結構繫結在一起,使用函式bind

#include<sys/types.h>
#include<sys/socket.h>
int bind(int sockfd,const struct sockaddr *my_addr,socklen_t addrlen);

與TCP並沒有什麼差異,bind()函式的作用是將一個套接字檔案描述符與一個本地地址繫結在一起,即把傳送資料的埠地址和IP地址進行了指定。

當成繫結之後,就可以使用recvfrom接收資料了

#include<sys/types.h>
#include<sys/socket.h>
ssize_t recv(int s,void *buf,size_t len,int flags);
ssize_t recvfrom(int s,void *buf,size_t len,int flags,struct sockaddr  *from,socklen_t *fromlen);

可以看出來recvfrom主要是比recv函式多了一個本地地址結構,所以不需要進行連線,只需要接收時指定傳送方地址就可以

然後下來是我們的客戶端

大體為建立套接字,提取伺服器端地址結構,收發資料

前面兩個步驟上面有提到,主要是發資料的話,要用到sendto()

#include<sys/types.h>
#include<sys/socket.h>
ssize_t send(int s,const void*buf,size_t len,int flags);
ssize_t sendto(int s,const void *buf,size_t len,int flags,const struct sockaddr *to,socklen_t tolen);

和send主要區別就在於第4個引數,表示接收資料的主機地址資訊,第5個引數為第4個引數所指向內容的長度

具體程式碼如下

伺服器端

#include<stdio.h>                                                                                                                                                                             
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<netinet/in.h>
#include<stdlib.h>
#define BUFF_LEN 256
void udpserv_echo(int s,struct sockaddr *client)
{
    int n;                              //接收資料長度
    char buff[BUFF_LEN];                //接收發送緩衝區
    socklen_t   len;                    //地址長度
    while(1) {
        len = sizeof(*client);
        n = recvfrom(s,buff,BUFF_LEN,0,client,&len);
        sendto(s,buff,n,0,client,len);  //將接收到的字元傳送回客戶端
    }
}
int main(void)
{
    int s;                              //套接字檔案描述符
    struct sockaddr_in  local;          //本地的地址資訊
    struct sockaddr_in  from;           //傳送方的地址資訊
    int from_len = sizeof(from);        //地址結構的長度
    int n;                              //接收到的資料長度
    char buf[128];                      //接受資料緩衝區
    s= socket(AF_INET,SOCK_DGRAM,0);    //初始化一個IPV4族的資料報套接字
    if(-1 == s) {
        perror("");
        exit(EXIT_FAILURE);
    }
 
    local.sin_family = AF_INET;
    local.sin_port = htons(8888);
    local.sin_addr.s_addr = htonl(INADDR_ANY);
 
    bind(s,(struct sockaddr *)&local,sizeof(local));
    udpserv_echo(s,(struct sockaddr *)&from);   //回顯處理函式
    return 0;
}

客戶端

#include<sys/types.h>                                                                 
#include<stdio.h>                                                                     
#include<unistd.h>                                                                    
#include<sys/socket.h>                                                                
#include<netinet/in.h>                                                                
#include<string.h>                                                                    
#define PORT_SERV 8888                                                                
#define BUFF_LEN 256                                                                  
void udpclie_echo(int s,struct sockaddr *to)                                          
{                                                                                     
    char buff[BUFF_LEN];                                                              
    struct sockaddr_in from;                                                          
    socklen_t len = sizeof(*to);                                                      
    sendto(s,buff,BUFF_LEN,0,to,len);                               //傳送給伺服器    
    recvfrom(s,buff,BUFF_LEN,0,(struct sockaddr *)&from,&len);      //從伺服器接收資料                                                                                                        
    printf("recved:%s\n",buff);                                                       
}                                                                                     
int main(int argc,char *argv[])                                                       
{                                                                                     
    int s;                                                          //檔案描述符      
    struct sockaddr_in addr_serv;                                   //地址結構        
    s = socket(AF_INET,SOCK_DGRAM,0);                               //建立UDP型別套接字
    memset(&addr_serv,0,sizeof(addr_serv));                         //清空地址結構    
    addr_serv.sin_family = AF_INET;                                                   
    addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);                                    
    addr_serv.sin_port = htons(PORT_SERV);                          //伺服器埠      
                                                                                      
    udpclie_echo(s,(struct sockaddr *)&addr_serv);                  //與伺服器互動    
    close(s);                                                                         
    return 0;                                                                         
}