Socket 基础编程(一)

Socket 基础编程(一)_第1张图片

一个通常意义上的Socket一般是分为Client与Server。
Server端需要实现:建立Socket-》绑定端口-》监听端口-》处理建链请求-》数据交互-》关闭链接。
Client端相对简单些:建立Socket-》发起TCP建链-》发送数据请求-》数据交互-》关闭链接。

如下是各API函数对应的TCP业务动作:
Socket 基础编程(一)_第2张图片

Client 的connect对应的TCP中的SYN建联请求,而服务器的accept对应的就是SYN ACK。
当Server端Accept成功后,会新分配一个fd用于和客户端做数据交互。
Close函数,则对应了四次挥手的动作。

如下是一简单的Server与Client实现:

Server:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#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;  
}

你可能感兴趣的:(网络)