1. 程式人生 > >實現簡單UDP伺服器客戶端模型

實現簡單UDP伺服器客戶端模型

UDP是無連線的,在資料的傳送之前不需要連線,只需要知道要發資料給誰,然後將資料發出即可,可以直接接收到其他人發來的資料,不必呼叫listen()和accept()函式。所以UDP中建立好套接字後,就可以直接進行資料的傳輸。 基於UDP的接收和傳送函式: #include <sys/types.h> #include <sys/socket.h> ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,  const struct sockaddr *dest_addr, socklen_t addrlen);
函式說明:      sendto() 用來將資料由指定的socket 傳給對方主機. 引數描述:      sockfd: 為已建好連線的socket, 如果利用UDP協議則不需經過連線操作      buf: 緩衝區      len:buf的大小      flags: 一般設0      dest_addr: 用來指定欲傳送的網路地址, 結構sockaddr 請參考bind()      addrlen: 為sockaddr 的結構長度. 返回值:      成功則返回實際傳送出去的字元數, 失敗返回-1, 錯誤原因存於errno 中. ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,  struct sockaddr *src_addr, socklen_t *addrlen);
函式說明:      用來接收遠端主機經指定的socket 傳來的資料, 並把資料存到由引數buf 指向的記憶體空間 引數描述:      sockfd:為已建好連線的socket      buf:緩衝區      len:buf大小      flags:收取收取資料的方式      src_addr: 用來指定欲傳送的網路地址, 結構sockaddr 請參考bind()      addrlen:為sockaddr 的結構長度 返回值:      成功則返回接收到的字元數,失敗返回-1,錯誤原因存於errno 中.
server:
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<stdlib.h>
static void usage(char* proc)
{
    printf("Usage: %s [local_ip] [local_port]", proc);
}

int main(int argc, char* argv[])
{
    if(argc != 3)
    {
    usage(argv[0]);
    }
    //建立套接字
    int sock = socket(AF_INET, SOCK_DGRAM,0);
    if(sock < 0)
    {
    perror("sock");
    return 1;
    }
    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argv[2]));
    local.sin_addr.s_addr = inet_addr(argv[1]);
    //將套接字描述符與IP和埠號進行繫結
    if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0 )
    {
    perror("bind");
    return 2;
    }

    struct sockaddr_in client;
    char buf[1024];
    while(1)
    {
    socklen_t len = sizeof(client);
    //接受客戶端發來的資訊,將客戶端的套接字資訊儲存於client裡
    ssize_t s = recvfrom(sock, buf, sizeof(buf)-1, 0, (struct sockaddr*)&client, &len);
    if(s > 0)
    {
            buf[s] = 0;
            printf("client [%s] [%d]: %s", inet_ntoa(client.sin_addr), ntohs(client.sin_port),buf);
            printf("Server : ");
            fflush(stdout);
        //從鍵盤讀入資訊
            int _s = read(0, buf, sizeof(buf)-1);
            buf[_s-1] = 0;
        //傳送資訊到客戶端
        sendto(sock, buf, strlen(buf), 0, (struct sockaddr*)&client, sizeof(client));
    }
    else
    {
        perror("recvfrom");
        return 3;
    }
    }
    return 0;
}
client:
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<sys/types.h>

static void Usage(char *proc)
{
    printf("Usage %s [server_ip] [server_port]\n", proc);
}
int main(int argc, char* argv[])
{
    if(argc != 3)
    {
    Usage(argv[0]);
    return 1;
    }
    //建立套接字,  注意使用udp套接字程式設計時應注意模式為SOCK_DGRAM
    int sock = socket(AF_INET, SOCK_DGRAM,0);
    if(sock < 0)
    {
    perror("socket");
    return 2;
    }
    //獲取伺服器套接字資訊
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(atoi(argv[2]));
    server.sin_addr.s_addr = inet_addr(argv[1]);

    char buf[1024];
    int len = sizeof(server);
    //用peer接收發送給客戶端的遠端主機socket資訊
    struct sockaddr_in peer;
    while(1)
    {
    printf("Please Enter# ");
    fflush(stdout);
    //從鍵盤寫入內容到緩衝區
    ssize_t s = read(0, buf, sizeof(buf)-1);
    buf[s] = 0;
    socklen_t len1 = sizeof(peer);
    if(s >0)
    {
        printf("server# ");
        //將緩衝區內容通過套接字傳送到伺服器
        sendto(sock, buf, strlen(buf), 0, (struct sockaddr*)&server, sizeof(server));
        //在從套接字中讀取伺服器的迴應資訊
        ssize_t _s = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr*)&peer, &len1);
        if(_s > 0)
        {
        buf[_s] = 0;
        printf("%s\n", buf);
        }
    }
    }
    return 0;
}