新聞中心
學習筆記:解決 linux c socket 異常問題

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


咨詢
建站咨詢
