簡單的UDP實現

根據UDP協議的特性,我們實現一個簡單的回顯服務器。

UDP協議:
傳輸層協議
無連接
不可靠
面向數據報

服務器代碼:

   ///////////////                                                                                                                                        
   // UDP版本的服務器
   // 1.綁定端口號
   // 2.服務器7*24小時等待客戶端發送的請求
   // 3.把響應發回客服端
   //////////////

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>

void service(int sock)
{
    char buf[128];
    for(;;)
    {
        //臨時的sockaddr_in 結構體接收
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        buf[0] = 0;
        //接收客戶端發來的數據   數據存在buf
        ssize_t s  = recvfrom(sock,buf,sizeof(buf)-1,\
                              0,(struct sockaddr*)&peer,&len);

        if(s > 0)
        {
            buf[s] = 0;
            //打印從哪個客戶端接收到的數據
            printf("[%s,%d] # %s\n",inet_ntoa(peer.sin_addr),\
                            ntohs(peer.sin_port),buf);
            //把響應發送給客戶端   buf
            sendto(sock,buf,strlen(buf),0,\
                   (struct sockaddr*)&peer,len);
        }
    }
}

 // ./server 0  8080
int main(int arg,char *argv[])
{
    if(arg != 3)
    {
        printf("usage: %s [ip] [port]\n",argv[0]);
        return 1;
    }
    //SOCK_DGRAM表示UDP ipv4: AF_INETET 
    int sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock < 0)
    {
        printf("socket error!\n");
        return 2;
    }
    //初始化sockaddr_in local    IPV4: AF_INET 
    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argv[2]));
    //字符串IP地址 轉換成 in_addr_t   :inet_addr() 看博主博客的地址轉換函數的介紹
    local.sin_addr.s_addr = inet_addr(argv[1]);

    //綁定端口號
    if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0)
    {
        printf("bind error\n");
        return 3;
    }
    //業務  ---  回顯
    service(sock);

    close(sock);
    return 0;
}

客戶端代碼:

 // UDP 版本的客戶端
 // 1. 從標準輸入, 讀入一個字符串
 // 2. 把這個字符串通過 socket 發送給服務器
 // 3. 嘗試從服務器讀取響應數據
 // 4. 把響應結果寫到標準輸出上.
  ///////////////////////////////////////////////////////

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>

//client  127.0.0.1 8080

int main(int arg,char *argv[])
{
    if(arg != 3)
    {
        printf("usage: %s [ip] [port]\n",argv[0]);
        return 1;
    }
    //創建sock < 0 創建失敗  SOCK_DGRAM表示UDP ipv4: AF_INETET 
    int sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock < 0)
    {
        printf("socket error\n");
        return 2;


    //初始化 sockaddr_in  ipv4: AF_INETET  
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    //端口號:atoi 字符轉換成數字
    server.sin_port = htons(atoi(argv[2]));
    //IP地址轉換函數   ----看博主博客地址轉換函數的介紹
    server.sin_addr.s_addr = inet_addr(argv[1]);
    socklen_t len = sizeof(server);

    //緩衝區
    char buf[128];

    //回顯服務器,死循環
    for(;;)
    {
        buf[128] = 0;
        //從標準輸入中讀取存放在buf   sizeof(buf)-1 是爲了最後爲一個字節爲0 
        ssize_t s = read(0,buf,sizeof(buf)-1);
        if(s>0)
        {
            buf[s-1] = 0;

            //發送數據
            sendto(sock,buf,strlen(buf),0,(struct sockaddr*)&server,len);
            //接受數據
            s = recvfrom(sock,buf,sizeof(buf)-1,0,NULL,NULL);
            if(s > 0)
            {
                buf[s] = 0;
                printf("server echo# %s\n",buf);
            }
        }
    }

    close(sock);
    return 0;
}

運行結果:
client:
這裏寫圖片描述

server:
這裏寫圖片描述

ps:

發送函數:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);

sockfd: socket
const void *buf: 緩衝區地址
size_t len:緩衝區的大小,buf的大小
int flags: 0
const struct sockaddr *dest_addr,結構體的地址
socklen_t addrlen : 結構體大小


接收函數:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

int sockfd:socket 
void *buf:緩衝區地址
size_t len:緩衝區大小
int flags:0
struct sockaddr *src_addr:結構體地址
socklen_t *addrlen:結構體大小
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章