新聞中心
在使用Linux下C語言Socket編程時,我們經(jīng)常會遇到阻塞(Blocking)和非阻塞(Non-blocking)的概念。那么什么是Socket阻塞機(jī)制?為什么會出現(xiàn)阻塞?如何進(jìn)行處理?

一、什么是Socket阻塞機(jī)制?
在C語言中使用Socket進(jìn)行網(wǎng)絡(luò)編程時,阻塞指的是程序停止或暫停執(zhí)行,直到某個事件發(fā)生才能繼續(xù)執(zhí)行。阻塞是指在程序讀寫數(shù)據(jù)的過程中,如果條件不符合通信的要求,程序就會停止執(zhí)行,直到滿足條件才能繼續(xù)執(zhí)行。這里的“條件”指的是網(wǎng)絡(luò)條件,如網(wǎng)絡(luò)是否暢通、目標(biāo)主機(jī)是否在線、數(shù)據(jù)包是否順利傳輸?shù)取?/p>
Socket阻塞機(jī)制是指在Socket通信過程中,如果有需要等待的事件,Socket會暫停進(jìn)程的執(zhí)行,直到事件出現(xiàn)為止。例如,當(dāng)我們執(zhí)行Socket的accept函數(shù)時,如果有客戶端連接請求尚未到達(dá),程序就會一直處于阻塞狀態(tài),直到有客戶端連接請求到達(dá),程序才會恢復(fù)運行。
二、為什么會出現(xiàn)阻塞?
1. 服務(wù)器忙碌
當(dāng)服務(wù)器負(fù)載較重時,就容易發(fā)生阻塞。如果某個服務(wù)器在處理請求的過程中,任務(wù)量過大,導(dǎo)致服務(wù)器無法及時響應(yīng)請求,那么客戶端就會被迫等待,直到請求得到響應(yīng)。此時就會出現(xiàn)阻塞問題。
2. 網(wǎng)絡(luò)狀況不佳
除此以外,在網(wǎng)絡(luò)狀況不佳的情況下,也會出現(xiàn)阻塞。如果網(wǎng)絡(luò)延遲較高,數(shù)據(jù)包傳輸速度變慢,那么就會導(dǎo)致Socket通信過程中出現(xiàn)阻塞。
三、如何進(jìn)行處理?
1. 線程和進(jìn)程
為了避免出現(xiàn)阻塞,我們可以使用多線程或多進(jìn)程來對Socket進(jìn)行處理。將阻塞操作放在單獨的線程或進(jìn)程中,然后使用異步I/O來等待事件發(fā)生,可以避免整個程序的阻塞問題。
2. 非阻塞Socket
還可以使用非阻塞Socket進(jìn)行處理。非阻塞Socket是指在Socket通信過程中,程序執(zhí)行不會被阻塞,而是立即返回。此時,程序可以進(jìn)行其他操作,直到Socket準(zhǔn)備好。當(dāng)Socket準(zhǔn)備好時,程序會得到一個通知,然后程序會立即進(jìn)行讀入或發(fā)送操作,以達(dá)到流暢通信的目的。
3. 設(shè)置超時
此外,我們還可以在程序中設(shè)置超時。當(dāng)程序等待數(shù)據(jù)超過指定時間時,就會立即放棄等待,進(jìn)行其他操作。這種方式適用于程序需要在特定時間內(nèi)響應(yīng)的情況。
:
Socket阻塞機(jī)制是Socket通信過程中需要等待的事件引發(fā)的進(jìn)程阻塞。在編寫Socket程序時,要考慮網(wǎng)絡(luò)狀況和服務(wù)器負(fù)載等因素,合理選擇處理方法,如使用多線程或多進(jìn)程、使用非阻塞Socket和設(shè)置超時等。這些處理方式有助于提高程序的并發(fā)度和響應(yīng)速度,使程序在高并發(fā)和大流量情況下也可以保持流暢通信。
相關(guān)問題拓展閱讀:
- LINUX C下ACCEPT失敗,前面SOCKET,BIND,LISTEN都成功
- linux下C語言socket編程雙機(jī)互發(fā)數(shù)據(jù)
- Linux下Socket編程 怎樣實現(xiàn)客戶端之間互相通信
LINUX C下ACCEPT失敗,前面SOCKET,BIND,LISTEN都成功
應(yīng)答是要陵巖使用另外一個空的socket對象進(jìn)行應(yīng)尺坦御答。而且這個socket對象必須沒有被賦值。例信升如下面的程序段;
while (AcceptSock == SOCKET_ERROR)
{
AcceptSock = accept(ConnectSocket,NULL,NULL);
}
我建議 閱讀 《unix網(wǎng)絡(luò)編程》里面有很詳細(xì)的解釋
舉個例子:
你可以把socket的IO操作看做是等人
阻塞:
你站在和人越好的地毀念方等人,你們的約定了一個時槐森間,當(dāng)你等的時間超過了這個時間后你就可以離開這個地點去干其他的事情,否則你將繼續(xù)在這里等人。而INFINIT就是無限等待下去
非阻塞:
就是你不需要站在越好的地點等人,你可以作在離這個地點很近的纖明困一個咖啡廳喝茶聽音樂,但你能夠看到這個約定地點的情況,一旦有人來你就可以走過去和那個人見面
阻塞:人來了以后你可以之一時間見到,而不用別人等你
非阻塞:和你正在做的事情有關(guān),如果你在坐在咖啡廳看電視,就很有可能造成別人等你的情況了
看看errno,如果是EAGAIN或EWOULDBLOCK是正常的。
你bupt-is的吧?我也遇到這個問題了,換臺電腦就好了
linux下C語言socket編程雙機(jī)互發(fā)數(shù)據(jù)
這么專業(yè)的問題去專業(yè)的網(wǎng)站或搜索QQ群上問吧,百度里有空回答的怕沒幾個人知道。
這個問題很好辦啦,服務(wù)器接受一個連接請求,然后開一個線程或者進(jìn)程都可以,再在線程或者進(jìn)程里面采用其他技術(shù)實現(xiàn)同時收發(fā)(比如I/O復(fù)用,比如非阻塞I/O)??蛻舳艘部梢圆捎肐/O復(fù)用。
推薦資含尺攔料的話,《unix網(wǎng)絡(luò)編程》這本書很好,公認(rèn)的經(jīng)典,當(dāng)教科書用,這本書里有你想要的所有內(nèi)容。
ps:你基礎(chǔ)太差,多補(bǔ)補(bǔ)吧,別想一下吃困桐個胖子。
另外我這里正好有個例子滿足你的要求,貼給你,自己寫的,不是網(wǎng)上找的,用的是多進(jìn)程加I/O復(fù)用技術(shù):
server端:
/****************************************************************
**
**
**
****************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFLEN 1024
#define MAX(a,b) ((a)>(b)?(a):(b))
typedef void Sigfunc (int);
void str_echo(FILE *,int);
//Sigfunc *signal(int, Sigfunc *);
int main(int argc,char **argv)
{
int connfd,listenfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in cliaddr,servaddr;
void sig_chld(int);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(5358);
bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
listen(listenfd,8);
signal(SIGCHLD,sig_chld);
while(1)
{
clilen = sizeof(cliaddr);
if((connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&clilen)) 0)
{
printf(“child %d terminated\n”,pid);
}
return;
}
client端:
#include
#include
#include
#include
#include
#include
#include
#define MAX(a,b) (a)>(b)?(a):(b)
int main()
{
int s,connectReturn, maxfd;
fd_set rset;
char sendbuf = {0};
char recvbuf = {0};
long port=5358;
s=socket(PF_INET,SOCK_STREAM,0);
struct sockaddr_in sa;
sa.sin_family=AF_INET;
sa.sin_addr.s_addr=inet_addr(“127.0.0.1”);
sa.sin_port=htons(port);
connectReturn=connect(s,(struct sockaddr *)&sa,sizeof(sa));
printf(“%d\n”,connectReturn);
FD_ZERO(&rset);
while(1)
{
FD_SET(fileno(stdin), &rset);
FD_SET(s, &rset);
maxfd=MAX(fileno(stdin), s) + 1;
select(maxfd, &rset, NULL, NULL, NULL);
if(FD_ISSET(fileno(stdin), &rset))
{
scanf(“%s”,sendbuf);
send(s,sendbuf,strlen(sendbuf),0);
bzero(sendbuf, 1024);
}
else if(FD_ISSET(s, &rset))
{
memset(recvbuf,0,1024);
recv(s,recvbuf,1024,0);
printf(“remote: %s\n”,recvbuf);
}
}
return 0;
Linux下Socket編程 怎樣實現(xiàn)客戶端之間互相通信
網(wǎng)絡(luò)的Socket數(shù)據(jù)傳輸是一種特殊的I/O,Socket也是一種文件描述符。Socket也具有一個類似于打開文件的函數(shù)調(diào)用Socket(),該函數(shù)返回一個整型的Socket描述符,隨后的連接建立、數(shù)據(jù)傳輸?shù)炔僮鞫际峭ㄟ^該Socket實現(xiàn)的。
下面用Socket實現(xiàn)一個windows下的c語言socket通信例子,這里我們客戶端傳遞一個字符串,服務(wù)器端進(jìn)行接收。
【服務(wù)器端】
#include “stdafx.h”
#include
#include
#include
#define SERVER_PORT 5208 //偵聽端口
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int ret, nLeft, length;
SOCKET sListen, sServer; //偵聽套接字,連接套接字
struct sockaddr_in saServer, saClient; //地址信息
char *ptr;//用于遍歷信息的指針
//WinSock初始化
wVersionRequested=MAKEWORD(2, 2); //希望使用的WinSock DLL 的版本
ret=WSAStartup(wVersionRequested, &wsaData);
if(ret!=0)
{
printf(“WSAStartup() failed!\n”);
return;
}
//創(chuàng)建Socket,使用TCP協(xié)議
sListen=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sListen == INVALID_SOCKET)
{
WSACleanup();
printf(“socket() faild!\n”);
return;
}
//構(gòu)建本地地址信息
saServer.sin_family = AF_INET; //地址家族
saServer.sin_port = htons(SERVER_PORT); //注意轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)序
saServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //使用INADDR_ANY 指示任意地址
//綁定
ret = bind(sListen, (struct sockaddr *)&saServer, sizeof(saServer));
if (ret == SOCKET_ERROR)
{
模核printf(“bind() faild! code:%d\n”, WSAGetLastError());
closesocket(sListen); //關(guān)閉套接字
WSACleanup();
return;
}
//偵聽連接請求
ret = listen(sListen, 5);
if (ret == SOCKET_ERROR)
{
printf(“l(fā)isten() faild! code:%d\n”, WSAGetLastError());
closesocket(sListen); //關(guān)閉套接字
return;
}
printf(“Waiting for client connecting!\n”);
printf(“Tips: Ctrl+c to quit!\n”);
//阻塞等待接受客戶端連接
while(1)//循環(huán)監(jiān)聽客戶端,永遠(yuǎn)不停止,所以,在本項目中,我們沒有心跳包。
{
length = sizeof(saClient);
散碼喚 sServer = accept(sListen, (struct sockaddr *)&saClient, &length);
if (sServer == INVALID_SOCKET)
{
printf(“accept() faild! code:%d\n”, WSAGetLastError());
closesocket(sListen); //關(guān)閉套接字
WSACleanup();
return;
}
char receiveMessage;
nLeft = sizeof(receiveMessage);
ptr = (char *)&receiveMessage;
while(nLeft>0)
{
//接收數(shù)據(jù)
ret = recv(sServer, ptr, 5000, 0);
if (ret == SOCKET_ERROR)
{
printf(“recv() failed!\n”);
return;
}
if (ret == 0) //客戶端已經(jīng)關(guān)沖凱閉連接
{
printf(“Client has closed the connection\n”);
break;
}
nLeft -= ret;
ptr += ret;
}
printf(“receive message:%s\n”, receiveMessage);//打印我們接收到的消息。
}
// closesocket(sListen);
// closesocket(sServer);
// WSACleanup();
}
【客戶端】
#include “stdafx.h”
#include
#include
#include
#define SERVER_PORT 5208 //偵聽端口
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int ret;
SOCKET sClient; //連接套接字
struct sockaddr_in saServer; //地址信息
char *ptr;
BOOL fSuccess = TRUE;
//WinSock初始化
wVersionRequested = MAKEWORD(2, 2); //希望使用的WinSock DLL的版本
ret = WSAStartup(wVersionRequested, &wsaData);
if(ret!=0)
{
printf(“WSAStartup() failed!\n”);
return;
}
//確認(rèn)WinSock DLL支持版本2.2
if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup();
printf(“Invalid WinSock version!\n”);
return;
}
//創(chuàng)建Socket,使用TCP協(xié)議
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sClient == INVALID_SOCKET)
{
WSACleanup();
printf(“socket() failed!\n”);
return;
}
//構(gòu)建服務(wù)器地址信息
saServer.sin_family = AF_INET; //地址家族
saServer.sin_port = htons(SERVER_PORT); //注意轉(zhuǎn)化為網(wǎng)絡(luò)節(jié)序
saServer.sin_addr.S_un.S_addr = inet_addr(“192.168.1.127”);
//連接服務(wù)器
ret = connect(sClient, (struct sockaddr *)&saServer, sizeof(saServer));
if (ret == SOCKET_ERROR)
{
printf(“connect() failed!\n”);
closesocket(sClient); //關(guān)閉套接字
WSACleanup();
return;
}
char sendMessage=”hello this is client message!”;
ret = send (sClient, (char *)&sendMessage, sizeof(sendMessage), 0);
if (ret == SOCKET_ERROR)
{
printf(“send() failed!\n”);
}
else
printf(“client info has been sent!”);
closesocket(sClient); //關(guān)閉套接字
WSACleanup();
}
網(wǎng)絡(luò)的Socket數(shù)據(jù)傳輸是一種特殊的I/O,Socket也是一種文件描述符。Socket也具有一個類似于打開文件的函數(shù)調(diào)用Socket(),該函數(shù)返回一個整型的Socket描述符,隨后的連接建立、數(shù)據(jù)傳輸?shù)炔僮鞫际峭ㄟ^該銀鉛搜Socket實現(xiàn)的。下面用Socket實現(xiàn)一個windows下的c語言socket通信例子,這里我們客戶端傳遞一個字符串,服務(wù)器端進(jìn)行接收。
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
【服務(wù)鋒歷激嘩器端】
#include “stdafx.h”
#include
#include
#include
#define SERVER_PORT 5208 //偵聽端口
void main()
關(guān)于linux c socket 阻塞的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
香港服務(wù)器選創(chuàng)新互聯(lián),2H2G首月10元開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務(wù)提供商,擁有超過10年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗。專業(yè)提供云主機(jī)、虛擬主機(jī)、域名注冊、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。
分享標(biāo)題:深入理解:Linux下C語言Socket阻塞機(jī)制(linuxcsocket阻塞)
URL分享:http://m.5511xx.com/article/codgijh.html


咨詢
建站咨詢
