轉行程序員淺談進程間的socket通信

我在之前的文章中曾說過,我現在開始負責車輛以太網應用層協議棧的開發和維護。

以太網通信說白了也屬於計算機通信的範疇,因此網絡通信的5層模型仍然適用於車輛通信領域。

既然設計到ECU間的網絡通信,那麼socket網絡編程的知識一定是必不可少的。

今天這篇文章就總結我這周學習的socket網絡編程的知識。

Socket編程常用的函數

首先,下圖是client與server之間的通信流程圖。
Socket通信流程

根據上面的socket通信流程圖,socket編程常用的函數如下:

  • 客戶端使用socket(), connect(), send(), recv(), close();

  • 服務端使用socket(), bind(), listen(), accept(), recv(), send(), close();

Socket通信的三次握手和四次揮手

Socket建立連接三次握手的流程
  • 第一次握手:client端先向server端發送連接請求

  • 第二次握手:server收到後,回覆ACK給client

  • 第三次握手:client端收到ACK後,回覆ACK給server

至此,client與server之間的網絡連接建立,可以順利進行數據傳輸。
三次握手建立連接

Socket斷開連接四次揮手的流程
  • 第一次揮手:client向server發送斷開連接請求

  • 第二次揮手:server收到client的請求,回覆ACK給client (這次揮手錶示server收到了client的請求,但是並不會立即斷開連接,可能還有未發送的數據)

  • 第三次揮手:server向client發送斷開連接請求(這次揮手錶示server端的數據已經發送完畢,client端可以斷開)

  • 第四次揮手:client收到了server的請求,發送ACK給server。之後client端處於等待狀態,過了一段時間後將socket關閉

至此,client與server之間的網絡連接斷開。
四次揮手斷開連接

簡單實現進程間的Socket的通信

實現步驟如下:
(1)使用socket套接字,並選擇TCP/IP協議,端口號爲6000

(2)客戶端發送“this is a test”到服務端

(3)服務端收到後打印字符串,並回復“test ok”到客戶端

(4)通信結束,斷開連接

客戶端socket通信的實現步驟
  • socket()創建socket

  • 設置socket的屬性

  • connect()向服務端發起連接

  • send()向服務端發送消息

  • recv()等待服務端的消息

  • close()關閉socket,回收資源

//client.c
#include<stdio.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<netinet/in.h>
#define PORT 6000
int main()
{
    int socketfd, error;
    struct sockaddr_in serv_addr;
    
    //創建socket
    socketfd = socket(AF_INET, SOCK_STREAM, 0);
    //設置socket的屬性
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    //向服務端發起連接
    error = connect(socketfd, &serv_addr, sizeof(struct sockaddr));
    if(0 != error)
    {
        printf("connect server error.");
        return 0;
    }
    //向服務端發送消息
    char *buff = "this is a test";
    error = send(socketfd, buff, strlen(buff), 0);
    if(-1 == error)
    {
        printf("send message to server error.");
        return 0;
    }
    //等待接收服務端的消息
    char recv_buff[1024] = {0};
    error = recv(socketfd, recv_buff, 1024,0);
    if(-1 == error)
    {
	printf("receive error");
	return 0;
    }
    printf("Receive buff:%s\n", recv_buff);
    //關閉socket,回收資源
    close(socketfd);
    return 0;
}
服務端socket通信的實現步驟
  • socket()創建socket
  • bind()對socket進行綁定
  • listen()監聽綁定的socket,用於監聽來自客戶端的消息
  • accept()用於接收客戶端的連接請求和消息
  • recv()函數接收客戶端的消息,並將其保存到設置好的buffer中
  • send()函數用於服務端向客戶端發送消息
  • close()關閉socket,回收資源
//server.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#define PORT 6000
int main()
{
    int socketfd, clientfd, error;
    struct sockaddr_in server_addr, client_addr;
    int sin_size;
    char buff[1024] = {0};
    //創建socket
    socketfd = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == socketfd)
    {
        printf("create socket fail.");
        return 0;
    }
    //socket屬性設置
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    //綁定socket
    error = bind(socketfd, &server_addr, sizeof(struct sockaddr_in));
    if(0 != error)
    {
        printf("bind fail.");
        close(socketfd);
        return 0;
    }
    //監聽socket
    error = listen(socketfd, 5);
    if(0 != error)
    {
        printf("listen fail.");
        close(socketfd);
        return 0;
    }
    //接收客戶端的連接請求
    clientfd = accept(socketfd, (struct sockaddr*)&client_addr, &sin_size);
    //連接建立後,接收客戶端的消息
    error = recv(clientfd, buff, 1024,0);
    if(-1 == error)
    {
        printf("receive error");
        close(socketfd);
        return 0;
    }
    printf("Receive buff:%s\n", buff);
    //收到消息後,向客戶端發送響應
    char *send_buff = "test ok.";
    error = send(clientfd, send_buff, strlen(send_buff), 0);
    if(-1 == error)
    {
        printf("send error");
        close(socketfd);
        return 0;
    }
    //關閉socket,回收資源
    close(socketfd);
    
    return 0;
}

代碼完成後,使用gcc編譯代碼,生成server和client的可執行文件。

然後,在linux界面打開兩個命令行,先運行server進程,再運行client進程,即可觀察到兩個進程之間的通信。

總結

這篇文章承接的是之前《白話計算機網絡》,但當時工作較忙一直沒有更新。

此外,如果想繼續學習socket通信和網絡協議,推薦一個開源項目tinyhttp。該項目通過500行代碼,利用多線程和socket通信簡單實現了http協議,是很適合初學者學習的資源,強烈推薦!!!

我這兩天正在閱讀該項目的源碼,等把項目源碼吃透,會寫一篇總結出來。

參考資料:

https://www.cnblogs.com/niwotaxuexiba/p/9700764.html

https://blog.csdn.net/chenlycly/article/details/51657179

ps: 歡迎關注我的公衆號[酷酷的coder],分享轉行菜鳥程序員成長過程彙總的煩惱和反思.

酷酷的Coder

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章