新聞中心
在網(wǎng)絡(luò)通信中,端口是用來區(qū)分不同應(yīng)用程序的標識符。每個應(yīng)用程序都需要偵聽一個端口來接收來自網(wǎng)絡(luò)的數(shù)據(jù)傳輸。對于Linux C 編程而言,實現(xiàn)端口監(jiān)聽是非常重要的一項功能。本文將介紹Linux C編程中常見的端口監(jiān)聽實現(xiàn)方法。

1. 使用socket系統(tǒng)調(diào)用
socket(套接字)是Linux系統(tǒng)中用于網(wǎng)絡(luò)通信的重要API之一。通過socket,應(yīng)用程序可以創(chuàng)建一個網(wǎng)絡(luò)套接字,并通過這個套接字與網(wǎng)絡(luò)進行通信。
在Linux C編程中,我們可以使用socket系統(tǒng)調(diào)用來創(chuàng)建一個監(jiān)聽套接字,從而實現(xiàn)端口的監(jiān)聽。下面是具體的步驟:
① 創(chuàng)建監(jiān)聽套接字
通過socket()函數(shù)創(chuàng)建一個監(jiān)聽套接字。這個函數(shù)的之一個參數(shù)指定協(xié)議族(比如,IPv4或IPv6),第二個參數(shù)指定套接字的類型(比如,TCP或UDP),第三個參數(shù)指定協(xié)議類型(通常為0,表示使用默認協(xié)議)。
int listening_socket = socket(AF_INET, SOCK_STREAM, 0);
② 綁定套接字到端口
使用bind()函數(shù)將監(jiān)聽套接字綁定到指定端口。這個函數(shù)的之一個參數(shù)是監(jiān)聽套接字,第二個參數(shù)是一個sockaddr結(jié)構(gòu)體指針,用來描述端口和IP地址等信息。需要注意的是,sockaddr結(jié)構(gòu)體的成員必須按照網(wǎng)絡(luò)字節(jié)序進行填充。下面是一個示例:
struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address)); // 清空結(jié)構(gòu)體
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port_number); // 將端口號轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序
server_address.sin_addr.s_addr = htonl(INADDR_ANY); // 等價于0.0.0.0,表示綁定到所有網(wǎng)卡上
int ret = bind(listening_socket, (struct sockaddr*)&server_address, sizeof(server_address));
③ 開始監(jiān)聽
使用listen()函數(shù)將監(jiān)聽套接字設(shè)置成被動監(jiān)聽狀態(tài),等待客戶端發(fā)起連接請求。這個函數(shù)的之一個參數(shù)是監(jiān)聽套接字,第二個參數(shù)是等待連接請求的隊列長度(通常為5)。
int ret = listen(listening_socket, 5);
④ 處理客戶端連接
使用accept()函數(shù)接收客戶端連接請求,并返回一個新的套接字,用于與客戶端進行通信。這個函數(shù)的之一個參數(shù)是監(jiān)聽套接字,第二個參數(shù)是一個指向sockaddr結(jié)構(gòu)體的指針,用于存儲客戶端的IP地址和端口號。需要注意的是,accept()函數(shù)是一個阻塞函數(shù),如果沒有客戶端連接請求,程序?qū)⒁恢弊枞谶@里。
struct sockaddr_in client_address;
socklen_t client_address_len = sizeof(client_address);
int client_socket = accept(listening_socket, (struct sockaddr*)&client_address, &client_address_len);
2. 使用select系統(tǒng)調(diào)用
在多并發(fā)的網(wǎng)絡(luò)通信中,使用socket系統(tǒng)調(diào)用會帶來一個重要的問題:阻塞。如果只有一個客戶端連接請求,我們的程序仍然會阻塞在accept()函數(shù)處,無法響應(yīng)其他客戶端的請求。為了解決這個問題,可以使用select系統(tǒng)調(diào)用。
select()函數(shù)可以監(jiān)聽多個文件描述符,當(dāng)其中有文件描述符就緒(比如可以讀寫)時,它會返回,并且可以通過FD_ISSET()宏判斷哪些文件描述符已經(jīng)就緒。下面是使用select()函數(shù)實現(xiàn)端口監(jiān)聽的基本步驟:
① 創(chuàng)建監(jiān)聽套接字
同樣地,通過socket()函數(shù)創(chuàng)建一個監(jiān)聽套接字。
② 綁定套接字到端口
同樣地,使用bind()函數(shù)將監(jiān)聽套接字綁定到指定端口。
③ 開始監(jiān)聽
同樣地,使用listen()函數(shù)將監(jiān)聽套接字設(shè)置成被動監(jiān)聽狀態(tài),等待客戶端發(fā)起連接請求。但是這里我們不會阻塞在accept()函數(shù)處。
int max_fd = listening_socket;
fd_set read_set;
fd_set ready_set;
FD_ZERO(&read_set);
FD_SET(listening_socket, &read_set);
while (1) {
ready_set = read_set;
int ret = select(max_fd+1, &ready_set, NULL, NULL, NULL);
if (ret
perror(“select”);
exit(-1);
}
if (FD_ISSET(listening_socket, &ready_set)) {
// 有連接請求,處理連接
} else {
// 有其他數(shù)據(jù)到達,處理數(shù)據(jù)
}
}
在循環(huán)中,我們先使用FD_ZERO()和FD_SET()宏將監(jiān)聽套接字添加到read_set中,然后不斷監(jiān)聽中的文件描述符是否就緒。如果有文件描述符就緒,則使用FD_ISSET()宏判斷具體是哪一個文件描述符就緒,然后進行相應(yīng)的處理。需要注意的是,我們需要保證每次循環(huán)都重新賦值ready_set,因為這個會被select()函數(shù)修改。
3. 使用epoll系統(tǒng)調(diào)用
select系統(tǒng)調(diào)用雖然可以避免單線程、單進程網(wǎng)絡(luò)編程中的阻塞問題,但是在高并況下性能和擴展性較差。為了解決這個問題,Linux內(nèi)核引入了epoll系統(tǒng)調(diào)用。
epoll()函數(shù)可以同時監(jiān)聽多個文件描述符,并且只會將就緒的文件描述符加入到epoll實例中。這樣,我們可以輕松地實現(xiàn)高并發(fā)網(wǎng)絡(luò)編程。下面是使用epoll()函數(shù)實現(xiàn)端口監(jiān)聽的基本步驟:
① 創(chuàng)建epoll實例
使用epoll_create()函數(shù)創(chuàng)建一個epoll實例,返回一個文件描述符。這個函數(shù)的參數(shù)可以用來指定epoll實例中更大可以監(jiān)聽的文件描述符數(shù)量。
int epoll_fd = epoll_create(1024);
② 將監(jiān)聽套接字添加到epoll實例中
使用epoll_ctl()函數(shù)將監(jiān)聽套接字添加到epoll實例中,用于接收客戶端連接請求。這個函數(shù)的之一個參數(shù)是epoll實例的文件描述符,第二個參數(shù)是指令類型(比如添加、刪除、修改等),第三個參數(shù)是要監(jiān)聽的文件描述符,第四個參數(shù)是一個epoll_event結(jié)構(gòu)體,用于指定事件類型和處理方式。
struct epoll_event event;
memset(&event, 0, sizeof(event));
event.events = EPOLLIN | EPOLLET; // 監(jiān)聽可讀事件,邊緣觸發(fā)模式
event.data.fd = listening_socket; // 監(jiān)聽套接字的文件描述符
int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listening_socket, &event);
③ 循環(huán)監(jiān)聽套接字文件描述符
使用epoll_wt()函數(shù)循環(huán)監(jiān)聽epoll實例中的文件描述符,將就緒的文件描述符交給工作線程進行處理。這個函數(shù)的參數(shù)可以用來指定最多等待多長時間、最多等待多少文件描述符等。
struct epoll_event events[1024];
while (1) {
int n_ready = epoll_wt(epoll_fd, events, 1024, -1);
if (n_ready
perror(“epoll_wt”);
exit(-1);
}
for (int i = 0; i
int fd = events[i].data.fd;
if (fd == listening_socket) {
// 監(jiān)聽套接字就緒,處理連接請求
} else {
// 其他文件描述符就緒,處理數(shù)據(jù)
}
}
}
需要注意的是,epoll實例提供了兩種觸發(fā)模式:邊緣觸發(fā)模式和水平觸發(fā)模式。邊緣觸發(fā)模式在文件描述符從未就緒變?yōu)榫途w的瞬間觸發(fā),處理方式更為靈活。而水平觸發(fā)模式則在文件描述符已經(jīng)就緒的情況下持續(xù)觸發(fā),適用于穩(wěn)定傳輸數(shù)據(jù)的場景。
端口監(jiān)聽是Linux C編程中非常重要的一項功能。本文介紹了三種常見的端口監(jiān)聽實現(xiàn)方法,分別是使用socket系統(tǒng)調(diào)用、select系統(tǒng)調(diào)用和epoll系統(tǒng)調(diào)用。讀者可以根據(jù)自己的需求選擇合適的方法進行開發(fā)。需要注意的是,網(wǎng)絡(luò)編程中容易出現(xiàn)阻塞和死鎖等問題,需要謹慎調(diào)試和處理,保證應(yīng)用程序的穩(wěn)定性和可靠性。
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián),建站經(jīng)驗豐富以策略為先導(dǎo)10多年以來專注數(shù)字化網(wǎng)站建設(shè),提供企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計,響應(yīng)式網(wǎng)站制作,設(shè)計師量身打造品牌風(fēng)格,熱線:028-86922220用C語言在Linux平臺上寫一個占用tcp8080端口的代碼。
那你要做好久
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
int sockfd,new_fd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
int sin_size;
/埋衡/建立TCP套接口
if((sockfd = socket(AF_INET,SOCK_STREAM,0))==-1)
{
printf(“create socket error”);
perror(“socket”);
exit(1);
}
//初始化結(jié)構(gòu)體,并綁定8080端口
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(8080);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero),8);
//綁定套接口
if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1)
{
perror(“bind socket error”);
exit(1);
}
//創(chuàng)建監(jiān)聽套接口
if(listen(sockfd,10)==-1)
{
perror(“l(fā)isten”);
exit(1);
}
//等待連接
while(1)
{
sin_size = sizeof(struct sockaddr_in);
printf(“server is run.\n”);
//如果建立連接,將產(chǎn)生一個全新的套接字
if((new_fd = accept(sockfd,(struct sockaddr *)&their_addr,&sin_size))==-1)
{
perror(“accept”);
exit(1);
}
printf(“accept success.\n”);
//生成一個子進程來完成和客戶端的會話,父進程繼續(xù)監(jiān)聽
if(!fork())
{
printf(“create new thred success.\n”);
//讀取客戶端發(fā)來的信息
int numbytes;
char buff;
memset(buff,0,256);
if((numbytes = recv(new_fd,buff,sizeof(buff),0))==-1)
{
perror(“recv”);
exit(1);
}
printf(“%s”,buff);
//將從客戶端接收到的信息再發(fā)回客戶端
if(send(new_fd,buff,strlen(buff),0)==-1)
perror(“send”);
close(new_fd);
exit(0);
}
close(new_fd);
}
close(sockfd);
linux虛擬機怎么查看tcp協(xié)議端口
在Linux虛擬機中查看tcp協(xié)議端口,可以使用netstat命令,它可以顯示當(dāng)前系統(tǒng)中所有正在使用的網(wǎng)絡(luò)端口以及網(wǎng)絡(luò)連接狀態(tài)。
1、查看所有TCP連接:
$ netstat -na | grep “tcp”
2、查看所有TCP監(jiān)聽端口:
$ netstat -na | grep “tcp” | grep “LISTEN”
3、查看指定端口的TCP連接:
$ netstat -na | grep “tcp” | grep “:80”
4、查看所有UDP端口
$ netstat -na | grep “udp”
5、查看指定端口的UDP連接
$ netstat -na | grep “udp” | grep “:53”
關(guān)于linux c 端口監(jiān)聽的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
成都創(chuàng)新互聯(lián)科技公司主營:網(wǎng)站設(shè)計、網(wǎng)站建設(shè)、小程序制作、成都軟件開發(fā)、網(wǎng)頁設(shè)計、微信開發(fā)、成都小程序開發(fā)、網(wǎng)站制作、網(wǎng)站開發(fā)等業(yè)務(wù),是專業(yè)的成都做小程序公司、成都網(wǎng)站建設(shè)公司、成都做網(wǎng)站的公司。創(chuàng)新互聯(lián)公司集小程序制作創(chuàng)意,網(wǎng)站制作策劃,畫冊、網(wǎng)頁、VI設(shè)計,網(wǎng)站、軟件、微信、小程序開發(fā)于一體。
分享文章:LinuxC編程:端口監(jiān)聽實現(xiàn)方法(linuxc端口監(jiān)聽)
分享鏈接:http://www.5511xx.com/article/dhjpscc.html


咨詢
建站咨詢
