1. 程式人生 > 其它 >一個簡單的socket網路程式設計

一個簡單的socket網路程式設計

1 socket程式設計流程

1.1 建立socket

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

domain 用於指定底層協議族,對 TCP/IP 協議族來說,應設定為 PF_INET(IPv4)或 PF_INET6(IPv6);type 用於指定服務型別,對 TCP/IP 族來說,SOCK_STREAM 表示使用 TCP 協議,SOCK_STREAM 表示使用 UDP 協議;protocol 是再選擇一個具體的協議,一般設為 0 使用預設協議即可。

 

1.2 命名socket

在服務端,需要呼叫 bind 將 socket 與 socket 地址進行繫結

,在客戶端則不需要呼叫 bind 進行繫結,作業系統會自動分配地址,當然也可以自行呼叫 bind 進行地址繫結,但是沒有那個必要。

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

所有專用 socket 地址(比如 TCP/IP 協議族的 sockaddr_in 和 sockaddr_in6 等)在使用時都需要轉換為通用 socket 地址 sockaddr, 所以在傳入第二個引數時往往需要進行強制轉換。

 

1.3 監聽socket

呼叫 listen 指定被監聽的 socket 和監聽佇列的最大長度。

int listen(int sockfd, int backlog);

  

1.4 接受連線

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

  

1.5 發起連線

客戶端通過 connect 與伺服器建立連線。

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

  

 

2 程式碼示例

2.1 服務端

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#include<sys/socket.h> 
#include<arpa/inet.h>

const int BUFSIZE = 1024;

int main(int argc, char* argv[]){

    if(argc <= 3){
        printf("usage: %s ip_adderss port number backlog\n", basename(argv[0]));
        return 1;
    }

    const char *ip = argv[1];
    int port = atoi(argv[2]);  //字串轉換整數
    int backlog = atoi(argv[3]);

    /*建立socket*/
    int sockfd = socket(PF_INET, SOCK_STREAM, 0);
    assert(sockfd >= 0);

    /*建立socket地址*/
    struct sockaddr_in address;
    bzero(&address, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_port = htons(port);  //主機位元組序轉換網路位元組序
    inet_pton(AF_INET, ip, &address.sin_addr);

    int ret = bind(sockfd, (struct sockaddr*) &address, sizeof(address));  //繫結socket地址
    assert(ret != -1);

    /*監聽socket*/
    ret = listen(sockfd, backlog);
    assert(ret != -1);

    printf("Waiting for connection...\n");

    struct sockaddr_in client;
    
    while(true){
        
        socklen_t client_length = sizeof(client);
        /*accept連線*/
        int connfd = accept(sockfd, (struct sockaddr *)&client, &client_length); 
        if(connfd < 0){
            printf("errno is: %d\n", errno);
            break;
        }

        printf("From client: IP is %s and Port is %d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));  //輸出客戶端IP和埠

        /*資料讀寫*/
        char recv_buffer[BUFSIZE];
        int n = recv(connfd, recv_buffer, BUFSIZE, 0);
        recv_buffer[n] = '\0';
        printf("Got %d bytes of data: %s\n", n, recv_buffer);

        close(connfd);
    }

    close(sockfd);

    return 0;
}

  

2.2 客戶端

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#include<sys/socket.h> 
#include<arpa/inet.h>

const int BUFSIZE = 1024;

int main(int argc, char* argv[]){

    if(argc <= 2){
        printf("usage: %s ip_adderss port number\n", basename(argv[0]));
        return 1;
    }

    const char *ip = argv[1];
    int port = atoi(argv[2]);  //字串轉換整數

    /*建立socket*/
    int sockfd = socket(PF_INET, SOCK_STREAM, 0);
    assert(sockfd >= 0);

    /*建立socket地址*/
    struct sockaddr_in address;
    bzero(&address, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_port = htons(port);  //主機位元組序轉換網路位元組序
    inet_pton(AF_INET, ip, &address.sin_addr);

    /*發起連線*/
    if(connect(sockfd, (struct sockaddr *)&address, sizeof(address)) < 0){
        printf("Connection failed\n");
        exit(1);
    }

    /*資料讀寫*/
    printf("Please enter information to the server:\n");
    char send_buffer[BUFSIZE];
    fgets(send_buffer, BUFSIZE, stdin);
    if(send(sockfd, send_buffer, strlen(send_buffer), 0) < 0){
        printf("errno is: %d\n", errno);
        exit(1);
    }

    close(sockfd);
    return 0;
}