經過TCP與簡易內存數據庫進行數據交互的實現

目的

運用TCP相關原理,實現一個簡單的server端和client端的數據庫交互程序,能夠將client端輸入的指令被server端解析,將返回信息又返送給client端。git

以前的簡單內存數據庫的實現:T-Tree、T*-Tree的理解與簡單內存數據庫的實現github

TCP/IP,socket等相關計算機網絡原理

七層網絡模型

七層網絡模型
圖片描述數據庫

TCP/IP

TCP/IP是互聯網協議簇的統稱。
TCP-transmission control protocal-傳輸控制協議
IP-Internet Protocal-因特網協議
UDP 是User Datagram Protocol 是無鏈接類型的傳輸層協議,segmentfault

socket是什麼

socket是對TCP/IP協議的封裝,socket翻譯爲套接字,socket是一個接口/插座。
TCPIP 是Socket的一種實現,Socket並不僅有TCP/IP。瀏覽器

兩種socket:stream sockets,datagram socket

socket其實不止兩種。
stream socket:串流式socket。是有鏈接類型的,網頁瀏覽器所使用的 HTTP 協議是用 stream sockets 取得網頁。
datagram socket:訊息式socket。是無鏈接類型的,用於語音通訊,視頻傳輸較多。網絡

TCP server

圖片描述

server端

socket()函數

#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

domain

一個地址描述。目前僅支持AF_INET格式,也就是說ARPA Internet地址格式。dom

type

指定socket類型。新套接口的類型描述類型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。經常使用的socket類型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。socket

protocol

指定協議。套接口所用的協議。如不想指定,可用0。經常使用的協議有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,它們分別對應TCP傳輸協議、UDP傳輸協議、STCP傳輸協議、TIPC傳輸協議。tcp

bind()函數

#include <sys/types.h>
#include <sys/socket.h>

int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

bind()將一本地地址與一socket捆綁.ide

sockfd

sockfd 是 socket() 傳回的 socket file descriptor。

my_addr

my_addr是指向包含你的地址資料丶名稱及 IP address 的 struct sockaddr 之指針。

addrlen

addrlen 是以 byte 爲單位的地址長度。

connect

#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

connect()從client端鏈接到server端

listen(),accept()

int listen(int sockfd, int backlog);


-----------------------------------------------------------------

#include <sys/types.h>
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

send(),recv()

int send(int sockfd, const void *msg, int len, int flags);
------------------------------------------------------------
int recv(int sockfd, void *buf, int len, int flags);

send() 會返回實際有送出的 byte 數,可能會少與所要傳送的數目。
recv()若返回0,則說明遠端那邊已經關閉了你的鏈接

close()

close(sockfd);

關閉socket。

一個tcp server 的示例代碼:

#include <netdb.h> 
#include <netinet/in.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#define MAX 80 
#define PORT 8080 
#define SA struct sockaddr 

// Function designed for chat between client and server. 
void func(int sockfd) 
{ 
    char buff[MAX]; 
    int n; 
    // infinite loop for chat 
    for (;;) { 
        bzero(buff, MAX); 

        // read the message from client and copy it in buffer 
        read(sockfd, buff, sizeof(buff)); 
        // print buffer which contains the client contents 
        printf("From client: %s\t To client : ", buff); 
        bzero(buff, MAX); 
        n = 0; 
        // copy server message in the buffer 
        while ((buff[n++] = getchar()) != '\n') 
            ; 

        // and send that buffer to client 
        write(sockfd, buff, sizeof(buff)); 

        // if msg contains "Exit" then server exit and chat ended. 
        if (strncmp("exit", buff, 4) == 0) { 
            printf("Server Exit...\n"); 
            break; 
        } 
    } 
} 

// Driver function 
int main() 
{ 
    int sockfd, connfd, len; 
    struct sockaddr_in servaddr, cli; 

    // socket create and verification 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd == -1) { 
        printf("socket creation failed...\n"); 
        exit(0); 
    } 
    else
        printf("Socket successfully created..\n"); 
    bzero(&servaddr, sizeof(servaddr)); 

    // assign IP, PORT 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port = htons(PORT); 

    // Binding newly created socket to given IP and verification 
    if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) { 
        printf("socket bind failed...\n"); 
        exit(0); 
    } 
    else
        printf("Socket successfully binded..\n"); 

    // Now server is ready to listen and verification 
    if ((listen(sockfd, 5)) != 0) { 
        printf("Listen failed...\n"); 
        exit(0); 
    } 
    else
        printf("Server listening..\n"); 
    len = sizeof(cli); 

    // Accept the data packet from client and verification 
    connfd = accept(sockfd, (SA*)&cli, &len); 
    if (connfd < 0) { 
        printf("server acccept failed...\n"); 
        exit(0); 
    } 
    else
        printf("server acccept the client...\n"); 

    // Function for chatting between client and server 
    func(connfd); 

    // After chatting close the socket 
    close(sockfd); 
}

client端

一個tcp client的示例代碼:

// Write CPP code here 
#include <netdb.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/socket.h> 
#define MAX 80 
#define PORT 8080 
#define SA struct sockaddr 
void func(int sockfd) 
{ 
    char buff[MAX]; 
    int n; 
    for (;;) { 
        bzero(buff, sizeof(buff)); 
        printf("Enter the string : "); 
        n = 0; 
        while ((buff[n++] = getchar()) != '\n') 
            ; 
        write(sockfd, buff, sizeof(buff)); 
        bzero(buff, sizeof(buff)); 
        read(sockfd, buff, sizeof(buff)); 
        printf("From Server : %s", buff); 
        if ((strncmp(buff, "exit", 4)) == 0) { 
            printf("Client Exit...\n"); 
            break; 
        } 
    } 
} 

int main() 
{ 
    int sockfd, connfd; 
    struct sockaddr_in servaddr, cli; 

    // socket create and varification 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd == -1) { 
        printf("socket creation failed...\n"); 
        exit(0); 
    } 
    else
        printf("Socket successfully created..\n"); 
    bzero(&servaddr, sizeof(servaddr)); 

    // assign IP, PORT 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    servaddr.sin_port = htons(PORT); 

    // connect the client socket to server socket 
    if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) { 
        printf("connection with the server failed...\n"); 
        exit(0); 
    } 
    else
        printf("connected to the server..\n"); 

    // function for chat 
    func(sockfd); 

    // close the socket 
    close(sockfd); 
}

經過TCP與簡易內存數據庫的數據交互

爲了讓client端和server中的內存數據庫,通訊若是server端和client創建鏈接以後則進入一個大循環,大循環的退出條件是client端發去「EXIT」,client端隨即斷開鏈接。

經過TCP和內存數據庫通訊的因此代碼

全部代碼都在github裏:slarsar/ttree_mmdb_tcp_server_client

參考

GeeksforGeeks
Beej's Guide to Network Programming 簡體中文版

相關文章
相關標籤/搜索