1. 程式人生 > >Socket 基礎程式設計(一)

Socket 基礎程式設計(一)

這裡寫圖片描述

一個通常意義上的Socket一般是分為Client與Server。
Server端需要實現:建立Socket-》繫結埠-》監聽埠-》處理建鏈請求-》資料互動-》關閉連結。
Client端相對簡單些:建立Socket-》發起TCP建鏈-》傳送資料請求-》資料互動-》關閉連結。

如下是各API函式對應的TCP業務動作:
這裡寫圖片描述

Client 的connect對應的TCP中的SYN建聯請求,而伺服器的accept對應的就是SYN ACK。
當Server端Accept成功後,會新分配一個fd用於和客戶端做資料互動。
Close函式,則對應了四次揮手的動作。

如下是一簡單的Server與Client實現:

Server:

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

#define SUCCESS 4
#define SERVERPORT 8888
#define
SOCKMAXCONN 1024
int main() { char buffer[1024] = {0}; struct sockaddr_in client_socket_addr; struct sockaddr_in server_socket_addr; socklen_t length = sizeof(client_socket_addr); ////////////////////////////////////////////////////////////////////////////// // struct sockaddr_in { // __kernel_sa_family_t sin_family; /* Address family */ // __be16 sin_port; /* Port number */
// struct in_addr sin_addr; /* Internet address */ // unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - sizeof(unsigned short int) - sizeof(struct in_addr)]; // }; /////////////////////////////////////////////////////////////////////////////// server_socket_addr.sin_family = AF_INET; server_socket_addr.sin_port = htons(SERVERPORT); server_socket_addr.sin_addr.s_addr = htonl(INADDR_ANY); ////////////////////////////////////////////////////////////////////////////// // Create a new socket of type TYPE in domain DOMAIN, using // protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically. // Returns a file descriptor for the new socket, or -1 for errors. // extern int socket (int __domain, int __type, int __protocol) __THROW; /////////////////////////////////////////////////////////////////////////////// int server_socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /////////////////////////////////////////////////////////////////////////////// // Give the socket FD the local address ADDR (which is LEN bytes long). // extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) /////////////////////////////////////////////////////////////////////////////// if (SUCCESS != bind(server_socket_fd, (struct sockaddr *)&server_socket_addr, sizeof(server_socket_addr))) { perror ("Bind Socket Failed: "); goto exit_half; } /////////////////////////////////////////////////////////////////////////////// // Prepare to accept connections on socket FD. // N connection requests will be queued before further requests are refused. // Returns 0 on success, -1 for errors. // extern int listen (int __fd, int __n) __THROW; /////////////////////////////////////////////////////////////////////////////// if(SUCCESS != listen(server_socket_fd, SOCKMAXCONN)) { perror ("Listen Socket Failed: "); goto exit_half; } /////////////////////////////////////////////////////////////////////////////// // A wait a connection on socket FD. // When a connection arrives, open a new socket to communicate with it, // set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting // peer and *ADDR_LEN to the address's actual length, and return the // new socket's descriptor, or -1 for errors. // This function is a cancellation point and therefore not marked with __THROW. // extern int accept (int __fd, __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len); /////////////////////////////////////////////////////////////////////////////// int client_conn = accept(server_socket_fd, (struct sockaddr*)&client_socket_addr, &length); if (-1 == client_conn) { perror ("Connect Socket Failed: "); goto exit_half; } /////////////////////////////////////////////////////////////////////////////// // Read N bytes into BUF from socket FD. // Returns the number read or -1 for errors. // This function is a cancellation point and therefore not marked with __THROW. // extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags); /////////////////////////////////////////////////////////////////////////////// int client_len = recv(client_conn, buffer, sizeof(buffer), 0); if (-1 == client_len) { perror ("Recv Socket Failed: "); goto exit; } /////////////////////////////////////////////////////////////////////////////// // Send N bytes of BUF to socket FD. Returns the number sent or -1. // This function is a cancellation point and therefore not marked with __THROW. // extern ssize_t send (int __fd, const void *__buf, size_t __n, int __flags); /////////////////////////////////////////////////////////////////////////////// if (-1 == send(client_conn, buffer, client_len, 0)) { perror ("Send Socket Failed: "); goto exit; } printf("Received Request: %s !\n", buffer); goto exit; exit: ////////////////////////////////////////////////////////////////////////////// // Close the file descriptor FD. // This function is a cancellation point and therefore not marked with // __THROW. // extern int close (int __fd); ////////////////////////////////////////////////////////////////////////////// close(client_conn); close(server_socket_fd); return SUCCESS; exit_half: close(server_socket_fd); return SUCCESS; }

Client:

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

#define SUCCESS 0
#define SERVERPORT 8888

int main()
{   
    char buffer[1024] = {0};
    char *send_msg = "Hello World!";

    struct sockaddr_in server_socket_addr = {0};
    socklen_t server_addr_length = sizeof(server_socket_addr);

    server_socket_addr.sin_family = AF_INET;
    server_socket_addr.sin_port = htons(SERVERPORT);
    if( inet_pton(AF_INET, "127.0.0.1", &server_socket_addr.sin_addr) <= 0)
    {
        perror ("Inet_pton Socket Failed: ");
        goto exit;
    }

    //////////////////////////////////////////////////////////////////////////////
    //  Create a new socket of type TYPE in domain DOMAIN, using
    //  protocol PROTOCOL.  If PROTOCOL is zero, one is chosen automatically.
    //  Returns a file descriptor for the new socket, or -1 for errors.
    //  extern int socket (int __domain, int __type, int __protocol) __THROW;
    ///////////////////////////////////////////////////////////////////////////////

    int client_socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    //////////////////////////////////////////////////////////////////////////////
    //  Open a connection on socket FD to peer at ADDR (which LEN bytes long).
    //  For connectionless socket types, just set the default address to send to
    //  and the only address from which to accept transmissions.
    //  Return 0 on success, -1 for errors.
    //  This function is a cancellation point and therefore not marked with __THROW.
    //  extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);
    //////////////////////////////////////////////////////////////////////////////

    if(SUCCESS != connect (client_socket_fd, (struct sockaddr*)&server_socket_addr, server_addr_length))
    {
        perror ("Connect Socket Failed: ");
        goto exit;
    }


    ///////////////////////////////////////////////////////////////////////////////
    //  Send N bytes of BUF to socket FD.  Returns the number sent or -1.
    //  This function is a cancellation point and therefore not marked with __THROW.
    //  extern ssize_t send (int __fd, const void *__buf, size_t __n, int __flags);
    ///////////////////////////////////////////////////////////////////////////////

    if (-1 == send(client_socket_fd, send_msg, strlen("Hello World!"), 0))
    {
        perror ("Send Socket Failed: ");
        goto exit;
    }

    ///////////////////////////////////////////////////////////////////////////////
    //  Read N bytes into BUF from socket FD.
    //  Returns the number read or -1 for errors.
    //  This function is a cancellation point and therefore not marked with __THROW. 
    //  extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags);
    ///////////////////////////////////////////////////////////////////////////////

    int client_len = recv(client_socket_fd, buffer, sizeof(buffer), 0);
    if (-1 == client_len)
    {
        perror ("Recv Socket Failed: ");
        goto exit;
    }

    printf("Received Response: %s !\n", buffer);

    send(client_socket_fd, "BYE", strlen("BYE"), 0);

    goto exit;

exit:

    close(client_socket_fd);  
    return SUCCESS;  
}