新聞中心
學(xué)習(xí)筆記:解決 linux c socket 異常問(wèn)題

成都創(chuàng)新互聯(lián)從2013年開(kāi)始,先為大東等服務(wù)建站,大東等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為大東企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。
在 Linux C 開(kāi)發(fā)中,Socket 是最常用的網(wǎng)絡(luò)編程接口之一。然而,在 Socket 編程中,我們經(jīng)常會(huì)遇到各種各樣的異常問(wèn)題。本篇學(xué)習(xí)筆記將介紹在 Linux C Socket 編程中,如何解決相關(guān)異常問(wèn)題。
錯(cuò)誤處理
在 Socket 編程中,錯(cuò)誤處理是必不可少的一步。Socket 接口提供了一個(gè)名為 errno 的全局變量,它可以告訴我們最近一次 Socket 函數(shù)調(diào)用失敗的原因。
errno 的值是一個(gè)整數(shù),其定義在 errno.h 頭文件中。一般情況下,errno 的值為0表示沒(méi)有錯(cuò)誤,其他值表示錯(cuò)誤發(fā)生。例如,當(dāng)調(diào)用 socket 函數(shù)失敗時(shí),errno 的值可能為 EAFNOSUPPORT 表示地址族不支持。
errno 的值在每次函數(shù)調(diào)用之前必須重置為0,以便確保在函數(shù)調(diào)用失敗時(shí)判斷 errno 的值是否為0。如果不重置 errno,那么errno 的值可能是錯(cuò)誤發(fā)生的函數(shù)調(diào)用之前的其他函數(shù)的錯(cuò)誤值。
下面是一個(gè)簡(jiǎn)單的例子:
“`c
#include
#include
#include
int mn() {
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd
printf(“socket error: %d\n”, errno);
}
return 0;
}
“`
上述代碼中,我們嘗試創(chuàng)建一個(gè) TCP socket。如果 socket 函數(shù)調(diào)用失敗,那么 errno 的值將不為0,并輸出錯(cuò)誤信息。
阻塞與非阻塞模式
Socket 可以在阻塞或非阻塞模式下運(yùn)行。默認(rèn)情況下,Socket 是阻塞的。
在阻塞模式下,調(diào)用 read 和 write 函數(shù)時(shí),系統(tǒng)將一直等待數(shù)據(jù)準(zhǔn)備就緒或數(shù)據(jù)發(fā)送完成。這意味著,當(dāng)調(diào)用 read 函數(shù)時(shí),進(jìn)程會(huì)一直被阻塞,直到有數(shù)據(jù)可讀。同樣地,當(dāng)調(diào)用 write 函數(shù)時(shí),進(jìn)程會(huì)一直被阻塞,直到所有數(shù)據(jù)都被發(fā)送。
在非阻塞模式下,當(dāng)調(diào)用 read 或 write 函數(shù)時(shí),進(jìn)程將立即返回,而不管數(shù)據(jù)是否準(zhǔn)備就緒或是否已發(fā)送全部數(shù)據(jù)。在非阻塞模式下,read 和 write 函數(shù)的返回值可能是負(fù)數(shù),表示函數(shù)調(diào)用遇到了錯(cuò)誤。常見(jiàn)的錯(cuò)誤包括 EAGN 和 EWOULDBLOCK,這兩個(gè)錯(cuò)誤指示進(jìn)程需要稍后重新嘗試。
下面是一個(gè)簡(jiǎn)單的例子:
“`c
#include
#include
#include
#include
#include
#include
#define PORT 8080
int mn() {
int sockfd, connfd, flags;
struct sockaddr_in server_addr, client_addr;
char buffer[1024];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd
printf(“socket error: %d\n”, errno);
return 1;
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr))
printf(“bind error: %d\n”, errno);
return 1;
}
if (listen(sockfd, 10)
printf(“l(fā)isten error: %d\n”, errno);
return 1;
}
flags = fcntl(sockfd, F_GETFL, 0);
if (flags
printf(“fcntl F_GETFL error: %d\n”, errno);
return 1;
}
flags |= O_NONBLOCK;
if (fcntl(sockfd, F_SETFL, flags)
printf(“fcntl F_SETFL O_NONBLOCK error: %d\n”, errno);
return 1;
}
while (1) {
socklen_t len = sizeof(client_addr);
connfd = accept(sockfd, (struct sockaddr*)&client_addr, &len);
if (connfd
if (errno == EAGN || errno == EWOULDBLOCK) {
usleep(100);
continue;
} else {
printf(“accept error: %d\n”, errno);
break;
}
}
bzero(buffer, 1024);
if (read(connfd, buffer, 1024)
if (errno == EAGN || errno == EWOULDBLOCK) {
usleep(100);
} else {
printf(“read error: %d\n”, errno);
break;
}
}
printf(“message from client : %s\n”, buffer);
close(connfd);
}
close(sockfd);
return 0;
}
“`
上述代碼中,我們創(chuàng)建了一個(gè) TCP 服務(wù)器,并將其設(shè)置為非阻塞模式。在主循環(huán)中,我們不斷等待客戶端連接。當(dāng)有客戶端連接到達(dá)時(shí),我們使用非阻塞模式讀取數(shù)據(jù)。如果 read 函數(shù)返回 EAGN 或 EWOULDBLOCK,我們需要稍后重新嘗試。這意味著我們可能需要在下一次循環(huán)中再次調(diào)用 read 函數(shù)。否則,我們將打印來(lái)自客戶端的消息并關(guān)閉連接。
內(nèi)存泄漏
內(nèi)存泄漏是 Socket 編程中常見(jiàn)的錯(cuò)誤之一。在 C 語(yǔ)言中,我們必須手動(dòng)管理內(nèi)存,包括分配、釋放和復(fù)制內(nèi)存。如果我們忘記釋放內(nèi)存,那么可能會(huì)導(dǎo)致內(nèi)存泄漏。內(nèi)存泄漏可能會(huì)導(dǎo)致內(nèi)存不足、崩潰或其他嚴(yán)重問(wèn)題。
下面是一個(gè)例子:
“`c
#include
#include
#include
#include
#include
#define PORT 8080
int mn() {
int sockfd;
struct sockaddr_in server_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd
printf(“socket error: %d\n”, errno);
return 1;
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr))
printf(“bind error: %d\n”, errno);
return 1;
}
if (listen(sockfd, 10)
printf(“l(fā)isten error: %d\n”, errno);
return 1;
}
while (1) {
int connfd;
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
connfd = accept(sockfd, (struct sockaddr*)&client_addr, &len);
if (connfd
printf(“accept error: %d\n”, errno);
return 1;
}
char* buffer = (char*)malloc(1024);
if (read(connfd, buffer, 1024)
printf(“read error: %d\n”, errno);
return 1;
}
printf(“message from client : %s\n”, buffer);
free(buffer);
close(connfd);
}
close(sockfd);
return 0;
}
“`
上述代碼中,我們將從客戶端讀取的數(shù)據(jù)存儲(chǔ)在 buffer 變量中。然而,我們忘記了釋放 buffer。這可能會(huì)導(dǎo)致內(nèi)存泄漏,并最終導(dǎo)致內(nèi)存不足。
結(jié)論
相關(guān)問(wèn)題拓展閱讀:
- linux c 讀取socket問(wèn)題
- linux下socket編譯時(shí)出現(xiàn)綁定錯(cuò)誤
linux c 讀取socket問(wèn)題
這個(gè),我說(shuō)下,你那含早個(gè)read的函旁老衫數(shù)那個(gè)地方有問(wèn)題,你可以用一個(gè)while循環(huán) 來(lái)接收數(shù)據(jù) ,
while(read(sockfd,buf,1900) != 0)
{
printf(“%s”,buf);
}
但是這樣的話沒(méi)法保存,你看看再弄個(gè)buf來(lái)保存一下
數(shù)據(jù)在網(wǎng)絡(luò)中輿不運(yùn)腔是一次就傳完 ,多次接收才能正常p
linux下socket編譯時(shí)出現(xiàn)綁定錯(cuò)誤
教你個(gè)調(diào)試方法,你把printf(“bind error”);換成printf(“bind error: %s\n”, strerror(errno)); 這樣可改蠢亂以看出哪里出錯(cuò)了.
我沒(méi)猜錯(cuò)的話錯(cuò)誤信息應(yīng)該是”Address already in use.” ,如果是這個(gè)錯(cuò)誤的話,你再等檔蠢一會(huì)核檔從新運(yùn)行server就可以了.
去紅旗Linux論壇去找找!
關(guān)于linux c socket 異常的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
成都服務(wù)器租用選創(chuàng)新互聯(lián),先試用再開(kāi)通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)提供簡(jiǎn)單好用,價(jià)格厚道的香港/美國(guó)云服務(wù)器和獨(dú)立服務(wù)器。物理服務(wù)器托管租用:四川成都、綿陽(yáng)、重慶、貴陽(yáng)機(jī)房服務(wù)器托管租用。
分享文章:「學(xué)習(xí)筆記」解決 Linux C Socket 異常問(wèn)題 (linux c socket 異常)
URL鏈接:http://www.5511xx.com/article/cdsojpo.html


咨詢
建站咨詢
