【Liunx Socket編程】——socket編程流程,以及創建一個簡單的連接,實現服務器端向客戶端發送數據

簡要概述

創建流程

服務端

  1. 創建一個套接字 ——socket()
  2. 綁定IP地址、端口等信息到socket上——bind()
  3. 監聽套接字——listen()
  4. 等待客戶端的連接請求——accept()
  5. 發送、接收數據——send()和recv(),或者read()和write()
  6. 關閉網絡連接——close()

客戶端

  1. 創建一個套接字——socket()
  2. 連接服務器——connect()
  3. 接收、發送數據——send()和recv(),或者read()和write()
  4. 關閉網絡連接——close()

代碼分析

實現服務器端向客戶端發送信息

以下socket編程用到的函數,可以點擊查看具體的socket常用函數解析

服務器端

一、創建一個套接字——socket()

//創建套接字
int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

二、綁定IP地址、端口等信息到socket上——bind()

struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));  //每個字節都用0填充
// 服務器端信息
serv_addr.sin_family = AF_INET;  //使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具體的IP地址
serv_addr.sin_port = htons(1258);  //端口
// 將套接字和IP、端口綁定
bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

三、監聽套接字——listen()

//進入監聽狀態,等待用戶發起請求
listen(serv_sock, 20);

四、等待客戶端的連接請求——accept()

//接收客戶端請求
struct sockaddr_in clnt_addr;
socklen_t clnt_addr_size = sizeof(clnt_addr);
int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

五、發送、接收數據——send()和recv(),或者read()和write()

//向客戶端發送數據
char str[] = "Hello World!";
write(clnt_sock, str, sizeof(str));

六、關閉網絡連接——close() 

//關閉套接字
close(clnt_sock);
close(serv_sock);

客戶端

一、創建一個套接字——socket()

//創建套接字
int sock = socket(AF_INET, SOCK_STREAM, 0);

二、連接服務器——connect()

先設置要連接的服務器的IP地址和端口等屬性,然後連接

struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
// 服務器端的信息
serv_addr.sin_family = AF_INET;  //使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具體的IP地址
serv_addr.sin_port = htons(1258);  //端口
//向服務器(特定的IP和端口)發起請求
connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

三、收發數據——send()和recv(),或者read()和write()

//讀取服務器傳回的數據
char buffer[40];
read(sock, buffer, sizeof(buffer)-1);

四、關閉網絡連接——close()

//關閉套接字
close(sock);

完整代碼

服務器端(service.c)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(){
        //創建套接字
        int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

        //將套接字和IP、端口綁定
        struct sockaddr_in serv_addr;
        memset(&serv_addr, 0, sizeof(serv_addr));  //每個字節都用0填充
        serv_addr.sin_family = AF_INET;  //使用IPv4地址
        serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具體的IP地址
        serv_addr.sin_port = htons(1258);  //端口
        bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
        //進入監聽狀態,等待用戶發起請求
        listen(serv_sock, 20);
        //接收客戶端請求
        struct sockaddr_in clnt_addr;
        socklen_t clnt_addr_size = sizeof(clnt_addr);
        int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
        //向客戶端發送數據
        char str[] = "Hello World!";
        write(clnt_sock, str, sizeof(str));

        //關閉套接字
        close(clnt_sock);
        close(serv_sock);
        return 0;
}

客戶端(client.c)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main(){
        //創建套接字
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        //向服務器(特定的IP和端口)發起請求
        struct sockaddr_in serv_addr;
        memset(&serv_addr, 0, sizeof(serv_addr));  //每個字節都用0填充
        serv_addr.sin_family = AF_INET;  //使用IPv4地址
        serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具體的IP地址
        serv_addr.sin_port = htons(1258);  //端口
        connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

        //讀取服務器傳回的數據
        char buffer[40];
        read(sock, buffer, sizeof(buffer)-1);

        printf("Message form server: %s\n", buffer);

        //關閉套接字
        close(sock);
        return 0;
}

運行

(需要開啓兩個終端)

先分別對兩個文件進行編譯(分別執行以下兩條命令)

gcc service.c -o service
gcc client.c -o client

然後先運行服務器端

./service

 再在另一個終端中運行客戶端

./client

執行完成

此時服務器端運行結束

客戶端也運行結束,並打印出內容

Message form server: Hello World!

服務器端與客戶端是全雙工連接,即服務器端既可以發送數據也可以接收數據,客戶端亦如此

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