1. 程式人生 > >基於windows的回聲udp服務器端/客戶端

基於windows的回聲udp服務器端/客戶端

soc 連接 err sockaddr word eof acl spa erro

udp是具有數據邊界的協議,傳輸中調用I/O函數的次數非常重要。輸入函數的調用次數要和輸出函數的調用次數完全一致,這樣才能保證接受全部已發送的數據。

tcp套接字中需註冊待傳輸數據的目標IP和端口,而udp中無需註冊。通過sendto函數傳遞數據的過程大約分為3個階段:
第1階段:向udp套接字註冊目標IP和端口號。
第2階段:傳輸數據。
第3階段:刪除udp套接字中註冊的目標地址信息。
每次調用sendto函數時都會重復上述過程。這種未註冊目標地址信息的套接字成為未連接套接字,反之,註冊了目標地址的套接字稱為連接套接字。udp默認屬於未連接套接字,創建已連接udp套接字只需調用connect函數,這樣可以提高效率。

服務器端:

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>

#define BUF_SIZE 64

void ErrorHandling(char* message);

int main()
{
    WSADATA wsa_data;
    SOCKET server_sock;
    SOCKADDR_IN server_addr, client_addr;
    int sz_client_addr;
    char message[BUF_SIZE];
    
int str_len; if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) ErrorHandling("WSAStartup() error."); server_sock = socket(PF_INET, SOCK_DGRAM, 0); if (server_sock == INVALID_SOCKET) ErrorHandling("socket() error."); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family
= AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(8000); if (bind(server_sock, (SOCKADDR*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) ErrorHandling("bind() error."); while (true) { sz_client_addr = sizeof(client_addr); str_len = recvfrom(server_sock, message, BUF_SIZE, 0, (SOCKADDR*)&client_addr, &sz_client_addr); sendto(server_sock, message, str_len, 0, (SOCKADDR*)&client_addr, sizeof(message)); } closesocket(server_sock); WSACleanup(); return 0; } void ErrorHandling(char* message) { fputs(message, stderr); fputc(\n, stderr); exit(1); }

使用連接套接字的客戶端:

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>

#define BUF_SIZE 64

void ErrorHandling(char* message);

int main()
{
    WSADATA wsa_data;
    SOCKET h_socket;
    SOCKADDR_IN server_addr;

    char message[BUF_SIZE];
    int str_len;

    if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0)
        ErrorHandling("WSAStartup() error.");

    h_socket = socket(PF_INET, SOCK_DGRAM, 0);
    if (h_socket == INVALID_SOCKET)
        ErrorHandling("socket() error.");

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(8000);

    if (connect(h_socket, (SOCKADDR*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR)
        ErrorHandling("connect() error.");

    while (true)
    {
        fputs("Insert message(q to quit): ", stdout);
        fgets(message, sizeof(message), stdin);
        if (!strcmp(message, "q\n") || !strcmp(message, "Q\n"))
            break;
        send(h_socket, message, strlen(message), 0);
        str_len = recv(h_socket, message, sizeof(message) - 1, 0);
        message[str_len] = 0;
        printf("Message from server: %s", message);
    }
    closesocket(h_socket);
    WSACleanup();
    return 0;
}

void ErrorHandling(char* message)
{
    fputs(message, stderr);
    fputc(\n, stderr);
    exit(1);
}

使用未連接套接字的客戶端:

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>

#define BUF_SIZE 64

void ErrorHandling(char* message);

int main()
{
    WSADATA wsa_data;
    SOCKET h_socket;
    SOCKADDR_IN server_addr, from_addr;

    char message[BUF_SIZE];
    int str_len;

    if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0)
        ErrorHandling("WSAStartup() error.");

    h_socket = socket(PF_INET, SOCK_DGRAM, 0);
    if (h_socket == INVALID_SOCKET)
        ErrorHandling("socket() error.");

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(8000);

    while (true)
    {
        fputs("Insert message(q to quit): ", stdout);
        fgets(message, sizeof(message), stdin);
        if (!strcmp(message, "q\n") || !strcmp(message, "Q\n"))
            break;
        sendto(h_socket, message, strlen(message), 0, (SOCKADDR*)&server_addr, sizeof(server_addr));
        int sz_from_addr = sizeof(from_addr);
        str_len = recvfrom(h_socket, message, BUF_SIZE, 0, (SOCKADDR*)&from_addr, &sz_from_addr);
        message[str_len] = 0;
        printf("Message from server: %s", message);
    }
    closesocket(h_socket);
    WSACleanup();
    return 0;
}

void ErrorHandling(char* message)
{
    fputs(message, stderr);
    fputc(\n, stderr);
    exit(1);
}

基於windows的回聲udp服務器端/客戶端