国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C語言網(wǎng)絡(luò)編程基礎(chǔ)(linux)

這篇具有很好參考價值的文章主要介紹了C語言網(wǎng)絡(luò)編程基礎(chǔ)(linux)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

文件描述符與套接字

在linux操作系統(tǒng)下,有萬物皆文件的概念,當一個進程想要打開/創(chuàng)建一個文件時,內(nèi)核會給進程返回一個文件描述符,文件描述符是一個非負數(shù),常用int類型表示,起到索引的作用,是為了高效管理進程打開/創(chuàng)建的文件的,指向的是被打開的文件。所有I/O的系統(tǒng)操作也都是通過文件描述符來的;每一個進程都有一個文件描述符表,里面記錄的就是進程打開/創(chuàng)建文件的記錄

套接字是一種特殊的文件描述符,用于進程和進程之間的網(wǎng)絡(luò)通信,常用在網(wǎng)絡(luò)編程中

進程和進程之間通信主要有六種方式,分別是:
1.管道
2.消息隊列
3.共享內(nèi)存
4.信號
5.信號量
6.套接字.

套接字便是其中的一種.

網(wǎng)絡(luò)編程的基本流程

C語言網(wǎng)絡(luò)編程基礎(chǔ)(linux),c語言,網(wǎng)絡(luò),linux
這個流程很經(jīng)典,就不過多贅述了.

基礎(chǔ)的函數(shù)和結(jié)構(gòu)體(持續(xù)更新)

函數(shù)太多了,這里只記錄一些常用的函數(shù)

socket函數(shù)

#include <sys/socket.h>

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

其中
domain表示指定套接字的地址族或協(xié)議族。常見的值包括:

AF_INET:用于IPv4 地址族。
AF_INET6:用于IPv6 地址族。
AF_UNIX 或 AF_LOCAL:用于本地(Unix 域)套接字通信。

type表示指定套接字的類型,常見的值包括:

SOCK_STREAM:用于基于流的 TCP 套接字。
SOCK_DGRAM:用于基于數(shù)據(jù)報的 UDP 套接字。
SOCK_RAW:用于原始套接字,允許更底層的數(shù)據(jù)包處理。

protocol 參數(shù)通常為 0,表示選擇默認的協(xié)議。在大多數(shù)情況下,操作系統(tǒng)會自動選擇正確的協(xié)議,例如,對于 IPv4 TCP 套接字,它會選擇 TCP 協(xié)議。

返回值:socket函數(shù)的返回值是一個文件描述符(fd),經(jīng)常作為網(wǎng)絡(luò)編程中其他函數(shù)的參數(shù).

常見的使用方式

int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

sockaddr和sockaddr_in結(jié)構(gòu)體

sockaddr

#include <sys/socket.h>
struct sockaddr {  
     sa_family_t sin_family;//地址族
    char sa_data[14]; //14字節(jié),包含套接字中的目標地址和端口信息               
   }; 

sockaddr已經(jīng)被sockaddr_in取代了,這里就不詳細說了。

sockaddr_in

#include<netinet/in.h>或#include <arpa/inet.h>

struct sockaddr_in {
    short int sin_family;      // 地址族(Address Family),通常為 AF_INET
    unsigned short int sin_port;  // 端口號(Port Number)
    struct in_addr sin_addr;     // IPv4 地址(32 位的 IPv4 地址)
    unsigned char sin_zero[8];   // 不使用,填充字節(jié)
};

sockaddr_in 是用于表示 IPv4 地址的 C 語言結(jié)構(gòu)體,通常在網(wǎng)絡(luò)編程中與套接字套接字相關(guān)的函數(shù)一起使用

常見的使用方式:

struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;//綁定地址族,使用ipv4
    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // 127.0.0.1 //綁定地址
    addr.sin_port = htons(8000); //綁定端口

bind函數(shù)

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

1.sockfd參數(shù)表示要進行綁定的套接字文件描述符(是socket函數(shù)的返回值)

2.sockaddr 結(jié)構(gòu)體是剛才上述所說的結(jié)構(gòu)體,但是sockaddr不如sockaddr_in好用,所以一般情況下是定義一個sockaddr_in結(jié)構(gòu)體,然后使用強制轉(zhuǎn)換成sockaddr類型

3.addrlen參數(shù)表示結(jié)構(gòu)體的長度

常用的使用方式:

 struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);  // 端口號 8080
    server_addr.sin_addr.s_addr = INADDR_ANY;  // 任意地址
    memset(server_addr.sin_zero, 0, sizeof(server_addr.sin_zero));
    
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("Bind failed");
        exit(1);
    }

listen函數(shù)

listen函數(shù)作用:讓套接字變成可以被動連接的狀態(tài),等待客戶端的連接

int listen(int sockfd, int backlog);

sockfd參數(shù)表示文件描述符

backlog參數(shù)表示等待連接隊列的最大長度,即在調(diào)用 accept 函數(shù)之前可以排隊等待的最大連接數(shù)。通常,這個值為一個正整數(shù),決定了同時等待的連接數(shù)量。

常用的使用方法:

int backlog = 5; // 最大等待連接數(shù)
if (listen(sockfd, backlog) == -1) {
        perror("Listen failed");
        exit(1);
    }

accept函數(shù)

accept 函數(shù)用于接受傳入的連接請求,通常在服務(wù)器端用于接受客戶端的連接

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

1.sockfd是文件描述符
2.addr是 sockaddr結(jié)構(gòu)體,用于接收客戶端的地址,端口等信息,所以跟Bind函數(shù)調(diào)用時的sockaddr要區(qū)分開來

3.addrlen是結(jié)構(gòu)體的大小

常見的使用方式:

 struct sockaddr_in new_addr;
 int new_sock;
 
 addr_size = sizeof(new_addr);
 new_sock = accept(sockfd, (struct sockaddr*)&new_addr, &addr_size);

返回值:在成功接受連接請求時返回一個新的套接字,該套接字用于與客戶端進行通信。這個新套接字是已連接套接字,它是服務(wù)器與客戶端之間的通信通道。

這里要重點強調(diào)一下,我們后續(xù)進行客戶端和服務(wù)端之間的通信時,使用的是accept函數(shù)返回的新套接字,而之前用socket函數(shù)創(chuàng)建的舊套接字仍然在監(jiān)聽新的連接請求(用于接收連接請求,而不是直接用來通信)

recv函數(shù)

recv 函數(shù)用于從已連接套接字(或者數(shù)據(jù)報套接字)接收數(shù)據(jù)
注意是已連接的套接字

int recv(int sockfd, void *buf, size_t len, int flags);

1.sockfd是文件描述符
2.buf是接收數(shù)據(jù)的緩沖區(qū)指針
3.len是緩沖區(qū)的大小
4.flags通常設(shè)置為0

返回值是recv函數(shù)讀到的字節(jié)數(shù),如果返回值為 -1,表示讀取失敗,失敗的原因會存儲在errno里面
recv函數(shù)的返回值總結(jié)

常見的使用方式:

int bytes_read=recv(sockfd,buffer,sizeof(buffer),0);

recv函數(shù)是一個阻塞函數(shù),如果在讀取時,發(fā)現(xiàn)并沒有數(shù)據(jù)可以讀,就會被阻塞住,如果不想被阻塞住,可以用fcntl函數(shù)將文件描述符設(shè)置為非阻塞模式,具體操作請看fcntl函數(shù).

recv 和 read 函數(shù)在某些方面類似,因為它們都用于從文件描述符中讀取數(shù)據(jù)。然而,它們有一些區(qū)別:

來源:
recv 是套接字庫函數(shù),用于在網(wǎng)絡(luò)編程中接收數(shù)據(jù)。它可以用于套接字(sockets)等網(wǎng)絡(luò)通信相關(guān)的操作。
read 是標準C I/O 函數(shù),通常用于文件描述符,但也可以用于套接字等。它更一般化,可用于讀取任何可讀的文件描述符。

參數(shù):
recv 在最后一個參數(shù)中可以指定額外的選項(flags),允許對接收操作進行控制。
read 沒有額外的選項參數(shù),它只接受文件描述符、緩沖區(qū)和長度。

錯誤處理:
recv 返回的錯誤值可能包含更多關(guān)于套接字通信的信息,如連接已斷開等。因此,錯誤代碼可能更詳細。
read 的錯誤碼可能相對簡單,不會提供關(guān)于底層通信的額外信息,但它可用于讀取多種文件類型。

用法:
recv 主要用于網(wǎng)絡(luò)編程,特別是在套接字通信中,用于接收數(shù)據(jù)。
read 主要用于文件和通用文件描述符的讀取,可用于從文件、管道、套接字等讀取數(shù)據(jù)。

writev函數(shù)

writev 函數(shù)用于將多個分散的數(shù)據(jù)寫入文件描述符(通常是文件或套接字)
也被稱為集中寫,與write函數(shù)的最大區(qū)別就是writev函數(shù)可以一次性寫出多個緩沖區(qū),而write函數(shù)一次性只能寫出一個緩沖區(qū)

#include <sys/uio.h>
ssize_t writev(int fd, const struct iovec *iov, int iovcnt);

1.fd參數(shù)表示文件描述符
2.iov參數(shù)表示指向iovec結(jié)構(gòu)體數(shù)組的結(jié)構(gòu)體指針
3.iovcnt表示數(shù)組中結(jié)構(gòu)體的數(shù)量

iovec數(shù)組

struct iovec {
    void *iov_base;    // 緩沖區(qū)的起始地址
    size_t iov_len;    // 緩沖區(qū)的長度
};

常見的使用方式:

    iov[0].iov_base = buf1; //緩沖區(qū)的起始地址
    iov[0].iov_len = strlen(buf1);//緩沖區(qū)的長度!
    iov[1].iov_base = buf2;
    iov[1].iov_len = strlen(buf2);

    int fd = 1;  
    ssize_t bytes_written = writev(fd, iov, 2);//將這兩個緩沖區(qū)的內(nèi)容全部
    //                                           寫入文件描述符

readv函數(shù)

用于把文件描述符中的數(shù)據(jù)一次性讀到多個緩沖區(qū)中,也叫作分散讀

ssize_t readv(int fd, const struct iovec *iov, int iovcnt);

使用方法和writev類似

iov[0].iov_base= buf1;
iov[0].iov_len=sizeof(buf1);
iov[1].iov_base = buf2;
iov[1].iov_len = sizeof(buf2);
ssize_t bytes_read = readv(fd,iov,2);

connect函數(shù)

connect 函數(shù)用于建立一個客戶端套接字與服務(wù)端套接字之間的連接。它在客戶端套接字上調(diào)用,指示客戶端要連接到指定的服務(wù)器地址和端口。

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

1.sockfd表示客戶端文件描述符
2.sockaddr表示要連接的地址及端口等信息(服務(wù)端的IP地址和監(jiān)聽的端口)
3.addrlen表示結(jié)構(gòu)體的大小

常見使用方式:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket");
        exit(1);
    }

    // 準備服務(wù)器地址信息
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);  // 服務(wù)器端口
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  // 服務(wù)器IP地址

    // 連接到服務(wù)器
    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("connect");
        exit(1);
    }

fcntl函數(shù)

fcntl 函數(shù)是一個在 Unix 和類 Unix 操作系統(tǒng)中使用的函數(shù),主要用于控制文件描述符(file descriptor)的屬性和執(zhí)行各種操作。這包括修改文件狀態(tài)標志、獲取或設(shè)置文件描述符的屬性、以及執(zhí)行非阻塞操作等。具體來說,fcntl 函數(shù)的一些常見用途包括:

1.修改文件狀態(tài)標志:通過 fcntl 函數(shù),你可以修改文件描述符的狀態(tài)標志,例如將文件設(shè)置為非阻塞模式,以便在讀寫操作時不會被阻塞。這是通過設(shè)置 O_NONBLOCK 標志實現(xiàn)的。

2.獲取或設(shè)置文件描述符屬性:你可以使用 fcntl 函數(shù)獲取或設(shè)置文件描述符的各種屬性,如獲取或設(shè)置文件的訪問模式、文件的擁有者、或文件的屏蔽字(file mode creation mask)等。

3.復制文件描述符:你可以使用 F_DUPFD 命令來復制一個文件描述符,這會創(chuàng)建一個新的文件描述符,指向與原始文件描述符相同的文件。

4.獲取或設(shè)置文件鎖:fcntl 函數(shù)還可用于獲取或設(shè)置文件鎖,以確保多個進程可以安全地訪問共享文件。你可以使用 F_GETLK 命令來獲取文件鎖信息,或使用 F_SETLK 和 F_SETLKW 命令來設(shè)置或阻塞文件鎖。

5.取消文件鎖:通過 F_SETLK 命令,你還可以用來取消現(xiàn)有的文件鎖。

參考鏈接:fcntl

#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */);

1.fd是要操作的文件描述符
2.cmd是對應(yīng)的操作命令,如下:

F_DUPFD:創(chuàng)建一個新的文件描述符,指向與原始文件描述符相同的文件。

F_GETFD:獲取文件描述符的標志。

F_SETFD:設(shè)置文件描述符的標志。

F_GETFL:獲取文件的狀態(tài)標志(如 O_RDONLY、O_WRONLY、O_NONBLOCK 等)。

F_SETFL:設(shè)置文件的狀態(tài)標志。

F_GETOWN:獲取文件描述符的所有權(quán)(如進程 ID 或進程組 ID)。

F_SETOWN:設(shè)置文件描述符的所有權(quán)。

F_GETLK:獲取文件鎖的信息。

F_SETLK:設(shè)置文件鎖,如果鎖已存在則返回錯誤。

F_SETLKW:設(shè)置文件鎖,如果鎖已存在則等待。

使用例子:

//對文件描述符設(shè)置非阻塞
int setnonblocking(int fd)
{
    int old_option = fcntl(fd, F_GETFL);
    int new_option = old_option | O_NONBLOCK;// O_NONBOLOCK為非阻塞標志.
    fcntl(fd, F_SETFL, new_option);
    return old_option;
}

因為文件描述符的標志是一個位掩碼,所以必須要先獲取原來的狀態(tài),再跟新狀態(tài)或運算,才可以修改文件描述符的狀態(tài).

stat函數(shù)

 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
 //獲取文件屬性,存儲在statbuf中
 int stat(const char *pathname, struct stat *statbuf);

1.參數(shù)pathname表示一個完整的文件路徑
2.參數(shù)statbuf是一個stat的結(jié)構(gòu)體指針,用來在調(diào)用stat函數(shù)之后,將文件的信息存儲在這個結(jié)構(gòu)體中

struct stat 
 {
   mode_t    st_mode;        /* 文件類型和權(quán)限 */
   off_t     st_size;        /* 文件大小,字節(jié)數(shù)*/
};

用stat函數(shù)可以獲取文件的類型,權(quán)限,以及大小等信息,常用于判斷文件是否存在,可讀,或者是不是目錄等

常見的使用方式:

查看路徑是否有文件存在:

 if(stat(m_real_file,&m_file_stat)<0) 
 //文件不存在

查看文件是否有可讀權(quán)限

if(!(m_file_stat.st_mode&S_IROTH)) 
//不可讀

查看該路徑是不是目錄

if(S_ISDIR(m_file_stat.st_mode))
//是目錄

mmap函數(shù)

用于將一個文件或其他對象映射到內(nèi)存,提高文件的訪問速度。

void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);
int munmap(void* start,size_t length);

start:映射區(qū)的開始地址,設(shè)置為0時表示由系統(tǒng)決定映射區(qū)的起始地址

length:映射區(qū)的長度

prot:期望的內(nèi)存保護標志,不能與文件的打開模式?jīng)_突

PROT_READ 表示頁內(nèi)容可以被讀取

flags:指定映射對象的類型,映射選項和映射頁是否可以共享

MAP_PRIVATE 建立一個寫入時拷貝的私有映射,內(nèi)存區(qū)域的寫入不會影響到原文件

fd:有效的文件描述符,一般是由open()函數(shù)返回

off_toffset:被映射對象內(nèi)容的起點

常見的使用方式:

 int fd=open(m_real_file,O_RDONLY);
    m_file_address=(char*)mmap(0,m_file_stat.st_size,PROT_READ,MAP_PRIVATE,fd,0);

epoll相關(guān)函數(shù)

epoll是linux操作系統(tǒng),內(nèi)核提供給用戶態(tài)專門用于多路復用的系統(tǒng)調(diào)用函數(shù),其作用是可以讓一個進程維護多個socket.

epoll的流程
1.使用epoll_create函數(shù)創(chuàng)建一個指向內(nèi)核事件表的文件描述符

2.使用epoll_ctl函數(shù)將想要監(jiān)聽的socket和想要監(jiān)聽的事件類型注冊到epoll上

3.使用epoll_wait函數(shù)等待事件到達,進程/線程通過對應(yīng)的事件處理方式處理事件

epoll_create

#include <sys/epoll.h>
int epoll_create(int size)

作用:創(chuàng)建一個指向epoll內(nèi)核事件表的文件描述符,返回值用于epoll其他函數(shù)的第一個參數(shù)

epoll_ctl函數(shù)

#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

用于將文件描述符注冊到epoll上,或者對已經(jīng)注冊好的文件描述符修改和刪除

1.第一個參數(shù)是epoll_create函數(shù)的句柄
2.第二個參數(shù)是一個命令,分別用三個宏表示注冊,修改,刪除

EPOLL_CTL_ADD (注冊新的fd到epfd),
EPOLL_CTL_MOD (修改已經(jīng)注冊的fd的監(jiān)聽事件),
EPOLL_CTL_DEL (從epfd刪除一個fd);

3.event參數(shù)表示要監(jiān)聽的事件

epoll_event結(jié)構(gòu)體

struct epoll_event {
__uint32_t events; //表示事件的類型
epoll_data_t data; //
};

events對應(yīng)的事件類型有如下幾種:
EPOLLIN:表示對應(yīng)的文件描述符可以讀(包括對端SOCKET正常關(guān)閉)

EPOLLOUT:表示對應(yīng)的文件描述符可以寫

EPOLLPRI:表示對應(yīng)的文件描述符有緊急的數(shù)據(jù)可讀(這里應(yīng)該表示有帶外數(shù)據(jù)到來)

EPOLLERR:表示對應(yīng)的文件描述符發(fā)生錯誤

EPOLLHUP:表示對應(yīng)的文件描述符被掛斷;

EPOLLET:將EPOLL設(shè)為邊緣觸發(fā)(Edge Triggered)模式,這是相對于水平觸發(fā)(Level Triggered)而言的

EPOLLONESHOT:只監(jiān)聽一次事件,當監(jiān)聽完這次事件之后,如果還需要繼續(xù)監(jiān)聽這個socket的話,需要再次把這個socket加入到EPOLL隊列里


epoll_data_t是一個共用體(聯(lián)合體)表示用戶數(shù)據(jù),用來存儲額外的信息

typedef union epoll_data {
    void *ptr;
    int fd;
    uint32_t u32;
    uint64_t u64;
} epoll_data_t;

ptr:一個指向 void 類型的指針,通常用于關(guān)聯(lián)一個任意類型的指針。
fd:一個整數(shù),通常用于關(guān)聯(lián)一個文件描述符(比如套接字描述符)。
u32:一個32位的無符號整數(shù)。
u64:一個64位的無符號整數(shù)。

epoll_ctl常見的使用方式:(這里如果看不太懂events下面還有詳解)

注冊:

     epoll_event event;
     event.data.fd = fd;//設(shè)置文件描述符!
 #ifdef ET
     event.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
 8#endif
 
#ifdef LT
    event.events = EPOLLIN | EPOLLRDHUP;
#endif

    if (one_shot)
        event.events |= EPOLLONESHOT;
    epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
    setnonblocking(fd);

刪除:

epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, 0);
   close(fd);

修改

void modfd(int epollfd, int fd, int ev)
 {
     epoll_event event;
     event.data.fd = fd;
 
 #ifdef ET
     event.events = ev | EPOLLET | EPOLLONESHOT | EPOLLRDHUP;
 #endif
 
#ifdef LT
    event.events = ev | EPOLLONESHOT | EPOLLRDHUP;
#endif

    epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event);
}

epoll_wait函數(shù)

用于等待事件的發(fā)生,當監(jiān)控的文件描述符上有事件發(fā)生時,返回有事件發(fā)生的文件描述符的個數(shù),通知進程處理事件

#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

1.epfd是epoll_wait函數(shù)創(chuàng)建的句柄
2.events表示內(nèi)核得到的事件的集合
3.maxevents表示events的大小,即能夠處理的最大事件數(shù)
4.timeout表示超時時間:
-1:阻塞
0:非阻塞
大于0:指定毫秒數(shù)

常見的使用方式:

int epfd = epoll_create(1); // 創(chuàng)建 epoll 實例
struct epoll_event events[MaxEvents]; // 用于存儲事件的數(shù)組

// 將需要監(jiān)聽的文件描述符添加到 epoll 實例(epfd)中,使用 epoll_ctl 函數(shù)。

int num_events = epoll_wait(epfd, events, MaxEvents, timeout);

epoll_ctl函數(shù)和epoll_wait函數(shù)中的events詳解:

epoll_ctl 函數(shù):
events 參數(shù)用于指定你希望監(jiān)聽的事件,這個參數(shù)是用于告訴 epoll 實例需要監(jiān)聽哪些事件的。在調(diào)用 epoll_ctl 函數(shù)時,你需要為 events 參數(shù)賦值,指定感興趣的事件類型,如 EPOLLIN(可讀事件)或 EPOLLOUT(可寫事件)等。
events 參數(shù)通常是一個位掩碼,可以使用位運算來指定多個事件,例如 EPOLLIN | EPOLLOUT 表示同時監(jiān)聽可讀和可寫事件。
events 參數(shù)的角色是告訴 epoll 實例你關(guān)心的事件類型以及要監(jiān)聽的文件描述符。

epoll_wait 函數(shù):
events 參數(shù)用于接收 epoll_wait 函數(shù)返回的已發(fā)生事件的信息。在調(diào)用 epoll_wait 之前,你不需要為 events 參數(shù)賦值,因為它將由 epoll_wait 函數(shù)填充。
當 epoll_wait 函數(shù)返回時,它會將已發(fā)生的事件信息填充到 events 數(shù)組中。你可以檢查每個事件的類型和相關(guān)的文件描述符,以確定發(fā)生了什么事件。

pthread相關(guān)函數(shù)

pthread_create

#include <pthread.h>
int pthread_create (pthread_t *thread_tid,                 //返回新生成的線程的id
                    const pthread_attr_t *attr,         //指向線程屬性的指針,通常設(shè)置為NULL
                    void * (*start_routine) (void *),   //處理線程函數(shù)的地址
                    void *arg);                         //start_routine()中的參數(shù)

pthread_create是C語言中,用于創(chuàng)建線程的函數(shù)
其中
thread_tid 是一個指向pthread_t類型的指針,用于存儲新創(chuàng)建線程的標識符(pthread_t類型也被成為線程標識符)

attr 是一個指向pthread_attr_t類型的指針,用于指定線程的屬性,通常為NULL

start_routine是一個指向返回類型為void * ,參數(shù)類型為(void *)的一個函數(shù)指針,該函數(shù)是線程要執(zhí)行的函數(shù),通常把線程的入口函數(shù)放在這里

arg 是一個 void類型的指針,作為start_routine函數(shù)中的參數(shù),在新線程啟動時,會作為參數(shù)傳遞給start_routine函數(shù)

當調(diào)用pthread_create函數(shù)之后,會在操作系統(tǒng)中創(chuàng)建一個新的線程,新的線程會直接去執(zhí)行start_routine指向的入口函數(shù).新線程可以和主線程同時執(zhí)行.各自執(zhí)行不同的代碼路徑

返回值為0表示線程創(chuàng)建成功,否則表示線程創(chuàng)建失敗.

pthread_join

int pthread_join(pthread_t thread, void **retval);

thread表示要等待的線程標識符
retval 是一個指向指針的指針,用于接受等待線程的返回值

主線程在調(diào)用pthread_join函數(shù)之后,會被阻塞,直到被等待的線程結(jié)束,同時,retval指向的指針將獲得等待線程的返回值(退出狀態(tài)).,如果不關(guān)心等待線程的返回值,可以將retval參數(shù)設(shè)置為NULL.

該函數(shù)主要用于線程間的同步操作,以確保主線程在等待子線程運行結(jié)束之后再繼續(xù)執(zhí)行
返回值為0表示函數(shù)使用成功,否則失敗

pthread_detach

#include <pthread.h>
int pthread_detach(pthread_t thread);

pthread_detach是C語言中用于 線程分離的函數(shù)
其中 thread 是 pthread_t類型的標識符,用于指定被分離的線程
線程分離指的是讓該線程與其主線程分離
在線程與其主線程分離之后,主線程就不再等待該線程的結(jié)束,不需要主線程調(diào)用pthread_join函數(shù)來等待該線程的終止并且該線程在結(jié)束時也會自動釋放資源,相當于是讓該線程與主線程脫離聯(lián)系.

當線程終止后,會釋放一些資源:
1.線程的??臻g釋放:現(xiàn)成的棧空間用來存放局部變量,函數(shù)調(diào)用等,線程終止后會自動釋放這些資源,供其他線程使用
2.線程描述符的釋放:線程描述符是內(nèi)核為線程分配的數(shù)據(jù)結(jié)構(gòu),用來跟蹤線程的狀態(tài)、優(yōu)先級等信息。當一個線程終止時,其線程描述符會被釋放,以允許新的線程創(chuàng)建并使用該描述符。

線程分離的意義是
主線程不需要在結(jié)束時顯示的等待子線程的結(jié)束,只要使用了線程分離,那么子線程會自行結(jié)束也會自行釋放資源,如果一個主線程不關(guān)心子線程的返回值和子線程的結(jié)束場景,我們就可以使用線程分離來提高代碼的簡潔性

pthread_exit

void pthread_exit(void *retval);

當線程執(zhí)行完畢時,可以通過pthread_exit函數(shù)來終止自身
其中retval 是指向需要傳遞給等待線程的退出狀態(tài)的指針.

參數(shù)retval 可以被傳遞給等待該線程的其他線程的pthread_join函數(shù),作為該線程的退出狀態(tài)

通俗來講,就是你可以在線程結(jié)束之前,動態(tài)開辟創(chuàng)建一個指針,用它來存儲和返回線程的退出狀態(tài),該線程在終止時,就會返回這個退出狀態(tài),相當于是線程的返回值;當我們在其他的線程中使用pthread_join函數(shù)等待這個線程結(jié)束時,這個線程的退出狀態(tài)就會保存在pthread_join的第二個參數(shù)里,相當于是線程退出狀態(tài)的一個傳遞.

int *result = malloc(sizeof(int));
    *result = 42;
    pthread_exit((void *)result);

調(diào)用pthread_exit函數(shù)會立刻終止當前正在執(zhí)行的線程,并且將控制權(quán)交還給主線程,如果被終止的線程是主線程,則會終止整個程序,如果不關(guān)心線程的退出狀態(tài),retval設(shè)置為NULL

pthread_exit(NULL); //不關(guān)心線程的退出狀態(tài)

最常見的用法是線程在執(zhí)行完任務(wù)后調(diào)用 pthread_exit 來退出。若線程沒有調(diào)用 pthread_exit,則當線程函數(shù)返回時,線程將自動調(diào)用 pthread_exit 并將返回值設(shè)為 NULL。同時允許傳遞退出狀態(tài)給等待線程的函數(shù),

pthread_join和pthread_exit連用的案例:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *thread_function(void *arg) {
    // 獲取整數(shù)參數(shù)值
    int *value = (int *)arg;

    printf("Thread %d is running!\n", *value);

    // 模擬線程執(zhí)行任務(wù)...
    // ...

    // 分配并返回退出狀態(tài)
    int *result = malloc(sizeof(int));
    *result = 42;
    pthread_exit((void *)result);
}

int main() {
    pthread_t thread;
    int thread_arg = 1;
    void *thread_result;

    // 創(chuàng)建線程
    if (pthread_create(&thread, NULL, thread_function, (void *)&thread_arg) != 0) {
        fprintf(stderr, "Failed to create thread\n");
        return 1;
    }

    // 等待線程結(jié)束并獲取退出狀態(tài)
    if (pthread_join(thread, &thread_result) != 0) {
        fprintf(stderr, "Failed to join thread\n");
        return 1;
    }

    printf("Thread exited with result: %d\n", *(int *)thread_result);

    // 釋放退出狀態(tài)的內(nèi)存
    free(thread_result);

    return 0;
}

MYSQL相關(guān)函數(shù)

MYSQL相關(guān)函數(shù)

信號量,互斥鎖,條件變量相關(guān)函數(shù)

信號量,互斥鎖,條件變量相關(guān)函數(shù)文章來源地址http://www.zghlxwxcb.cn/news/detail-725636.html

到了這里,關(guān)于C語言網(wǎng)絡(luò)編程基礎(chǔ)(linux)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • linux【網(wǎng)絡(luò)編程】之網(wǎng)絡(luò)基礎(chǔ)

    linux【網(wǎng)絡(luò)編程】之網(wǎng)絡(luò)基礎(chǔ)

    “協(xié)議” 是一種約定 軟件設(shè)計方面的優(yōu)勢—低耦合 分層依據(jù):功能比較集中,耦合度較高的模塊—高內(nèi)聚 每一層都要解決特定的問題 每一層都有自己匹配的協(xié)議,每一層協(xié)議都解決自己的問題 OSI(Open System Interconnection,開放系統(tǒng)互連)七層網(wǎng)絡(luò)模型稱為開放式系統(tǒng)互聯(lián)參

    2024年02月04日
    瀏覽(33)
  • 【網(wǎng)絡(luò)編程】Linux網(wǎng)絡(luò)編程基礎(chǔ)與實戰(zhàn)第三彈——網(wǎng)絡(luò)名詞術(shù)語

    數(shù)據(jù)包從源地址到目的地址所經(jīng)過的路徑,由一系列路由節(jié)點組成。 某個路由節(jié)點為數(shù)據(jù)包選擇投遞方向的選路過程。 路由器工作原理 路由器是連接因特網(wǎng)中各局域網(wǎng)、廣域網(wǎng)的設(shè)備,它會根據(jù)信道的情況自動選擇和設(shè)定路由,以最佳路徑,按前后順序發(fā)送信號的設(shè)備。

    2024年02月08日
    瀏覽(25)
  • 【Linux網(wǎng)絡(luò)編程一】網(wǎng)絡(luò)基礎(chǔ)1(網(wǎng)絡(luò)框架)

    【Linux網(wǎng)絡(luò)編程一】網(wǎng)絡(luò)基礎(chǔ)1(網(wǎng)絡(luò)框架)

    本篇開始總結(jié)網(wǎng)絡(luò)知識,系統(tǒng)部分到此結(jié)束。 網(wǎng)絡(luò)的本質(zhì)就是在獲取和生產(chǎn)數(shù)據(jù),而系統(tǒng)的本質(zhì)就是在處理數(shù)據(jù)。從網(wǎng)絡(luò)中獲取到數(shù)據(jù)利用系統(tǒng)調(diào)用來處理數(shù)據(jù)。而網(wǎng)絡(luò)的本質(zhì)也就是文件,我往文件里寫,就是往網(wǎng)卡里寫,往網(wǎng)卡里寫,就是往網(wǎng)絡(luò)里寫。 我們在生活中都是

    2024年02月19日
    瀏覽(16)
  • C++Linux網(wǎng)絡(luò)編程基礎(chǔ)

    當動態(tài)庫和靜態(tài)庫同時存在的時候,會優(yōu)先使用動態(tài)庫 。 靜態(tài)庫 1. 制作靜態(tài)庫 -c表示只編譯,-o則是說明需要指定文件名 2. 使用靜態(tài)庫 3. 庫文件的概念 程序在編譯時,會將庫文件的二進制代碼鏈接到目標程序中,這種方式稱為 靜態(tài)編譯 。 如果多個程序中用到了同一個靜

    2024年01月20日
    瀏覽(50)
  • 【Linux】網(wǎng)絡(luò)基礎(chǔ)+UDP網(wǎng)絡(luò)套接字編程

    【Linux】網(wǎng)絡(luò)基礎(chǔ)+UDP網(wǎng)絡(luò)套接字編程

    只做自己喜歡做的事情,不被社會和時代裹挾著前進,是一件很奢侈的事。 1. 首先計算機是人類設(shè)計出來提高生產(chǎn)力的工具,而人類的文明綿延至今一定離不開人類之間互相的協(xié)作,既然人類需要協(xié)作以完成更為復雜的工作和難題,所以計算機作為人類的工具自然也一定需要

    2024年02月08日
    瀏覽(89)
  • 《3.linux應(yīng)用編程和網(wǎng)絡(luò)編程-第8部分-3.8.網(wǎng)絡(luò)基礎(chǔ)》 3.8.1.網(wǎng)絡(luò)通信概述 3.8.3.網(wǎng)絡(luò)通信基礎(chǔ)知識2

    《3.linux應(yīng)用編程和網(wǎng)絡(luò)編程-第8部分-3.8.網(wǎng)絡(luò)基礎(chǔ)》 3.8.1.網(wǎng)絡(luò)通信概述 3.8.3.網(wǎng)絡(luò)通信基礎(chǔ)知識2

    ????進程間通信: 管道 、 信號量、 共享內(nèi)存, 技術(shù)多,操作麻煩 ? ??線程就是解決 進程間 通信 麻煩的事情,這是線程的 優(yōu)勢 3.8.1.網(wǎng)絡(luò)通信概述 3.8.1.1、從進程間通信說起: 網(wǎng)絡(luò)域套接字socket , 網(wǎng)絡(luò)通信其實就是位于網(wǎng)絡(luò)中不同主機上面? ? ? ? ? ? ? ? ? ?的?

    2024年02月15日
    瀏覽(27)
  • Linux高性能服務(wù)器編程 學習筆記 第五章 Linux網(wǎng)絡(luò)編程基礎(chǔ)API

    Linux高性能服務(wù)器編程 學習筆記 第五章 Linux網(wǎng)絡(luò)編程基礎(chǔ)API

    我們將從以下3方面討論Linux網(wǎng)絡(luò)API: 1.socket地址API。socket最開始的含義是一個IP地址和端口對(ip,port),它唯一表示了使用TCP通信的一端,本書稱其為socket地址。 2.socket基礎(chǔ)API。socket的主要API都定義在sys/socket.h頭文件中,包括創(chuàng)建socket、命名socket、監(jiān)聽socket、接受連接、發(fā)

    2024年02月07日
    瀏覽(41)
  • 初學記錄【linux應(yīng)用】 TCP/UDP 網(wǎng)絡(luò)編程 C語言

    初學記錄【linux應(yīng)用】 TCP/UDP 網(wǎng)絡(luò)編程 C語言

    以下內(nèi)容分別為TCP 與 UDP編程,內(nèi)容有相似或者重合部分,可根據(jù)流程 相互對照學習,都已經(jīng)附上源碼 。 **1.** socket 創(chuàng)建 tcp套接字 (監(jiān)聽的套接字) 2、IPv4套接字地址結(jié)構(gòu) #include netinet/in.h struct in_addr: 如果使用 Internet 所以 sin_family 一般為 AF_INET。 ? sin_addr 設(shè)置為 INADDR_AN

    2024年02月03日
    瀏覽(26)
  • 多人聊天室(帶私聊功能)Linux網(wǎng)絡(luò)編程基礎(chǔ)

    多人聊天室(帶私聊功能)Linux網(wǎng)絡(luò)編程基礎(chǔ)

    在和同學一起努力下終于完成了期末作業(yè)哈哈哈哈 文章目錄 目錄 前言 一、需求分析 二、功能設(shè)計 1.服務(wù)器端: 2.客戶端: 三、流程圖: 編程流程圖: 服務(wù)器流程圖: 客戶端流程圖: 四、運行效果: 項目源碼: 服務(wù)器源碼 客戶端源碼: 總結(jié): Linux網(wǎng)絡(luò)編程是我們這學

    2024年02月09日
    瀏覽(26)
  • Linux C++ 網(wǎng)絡(luò)編程基礎(chǔ)(2) : TCP多線程一個server對應(yīng)多個client

    作者:令狐掌門 技術(shù)交流QQ群:675120140 csdn博客:https://mingshiqiang.blog.csdn.net/ ??tcp編程時, 一個server可以對應(yīng)多個client, server端用多線程可以實現(xiàn). linux下多線程可以使用POSIX的線程函數(shù), 下面給出服務(wù)端和客戶端的代碼. ??Linux POSIX線程庫提供了一組函數(shù)來創(chuàng)建、管理和同步

    2024年02月13日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包