深入理解:Linux下C语言Socket阻塞机制 (linux c socket 阻塞)

在使用Linux下C语言Socket编程时,我们经常会遇到阻塞(Blocking)和非阻塞(Non-blocking)的概念。那么什么是Socket阻塞机制?为什么会出现阻塞?如何进行处理?

一、什么是Socket阻塞机制?

在C语言中使用Socket进行网络编程时,阻塞指的是程序停止或暂停执行,直到某个事件发生才能继续执行。阻塞是指在程序读写数据的过程中,如果条件不符合通信的要求,程序就会停止执行,直到满足条件才能继续执行。这里的“条件”指的是网络条件,如网络是否畅通、目标主机是否在线、数据包是否顺利传输等。

Socket阻塞机制是指在Socket通信过程中,如果有需要等待的事件,Socket会暂停进程的执行,直到事件出现为止。例如,当我们执行Socket的accept函数时,如果有客户端连接请求尚未到达,程序就会一直处于阻塞状态,直到有客户端连接请求到达,程序才会恢复运行。

二、为什么会出现阻塞?

1. 服务器忙碌

当服务器负载较重时,就容易发生阻塞。如果某个服务器在处理请求的过程中,任务量过大,导致服务器无法及时响应请求,那么客户端就会被迫等待,直到请求得到响应。此时就会出现阻塞问题。

2. 网络状况不佳

除此以外,在网络状况不佳的情况下,也会出现阻塞。如果网络延迟较高,数据包传输速度变慢,那么就会导致Socket通信过程中出现阻塞。

三、如何进行处理?

1. 线程和进程

为了避免出现阻塞,我们可以使用多线程或多进程来对Socket进行处理。将阻塞操作放在单独的线程或进程中,然后使用异步I/O来等待事件发生,可以避免整个程序的阻塞问题。

2. 非阻塞Socket

还可以使用非阻塞Socket进行处理。非阻塞Socket是指在Socket通信过程中,程序执行不会被阻塞,而是立即返回。此时,程序可以进行其他操作,直到Socket准备好。当Socket准备好时,程序会得到一个通知,然后程序会立即进行读入或发送操作,以达到流畅通信的目的。

3. 设置超时

此外,我们还可以在程序中设置超时。当程序等待数据超过指定时间时,就会立即放弃等待,进行其他操作。这种方式适用于程序需要在特定时间内响应的情况。

Socket阻塞机制是Socket通信过程中需要等待的事件引发的进程阻塞。在编写Socket程序时,要考虑网络状况和服务器负载等因素,合理选择处理方法,如使用多线程或多进程、使用非阻塞Socket和设置超时等。这些处理方式有助于提高程序的并发度和响应速度,使程序在高并发和大流量情况下也可以保持流畅通信。

相关问题拓展阅读:

LINUX C下ACCEPT失败,前面SOCKET,BIND,LISTEN都成功

应答是要陵岩使用另外一个空的socket对象进行应尺坦御答。而且这个socket对象必须没有被赋值。例信升如下面的程序段;

while (AcceptSock == SOCKET_ERROR)

{

AcceptSock = accept(ConnectSocket,NULL,NULL);

}

我建议 阅读 《unix网络编程》里面有很详细的解释

举个例子:

你可以把socket的IO操作看做是等人

阻塞:

你站在和人越好的地毁念方等人,你们的约定了一个时槐森间,当你等的时间超过了这个时间后你就可以离开这个地点去干其他的事情,否则你将继续在这里等人。而INFINIT就是无限等待下去

非阻塞:

就是你不需要站在越好的地点等人,你可以作在离这个地点很近的纤明困一个咖啡厅喝茶听音乐,但你能够看到这个约定地点的情况,一旦有人来你就可以走过去和那个人见面

阻塞:人来了以后你可以之一时间见到,而不用别人等你

非阻塞:和你正在做的事情有关,如果你在坐在咖啡厅看电视,就很有可能造成别人等你的情况了

看看errno,如果是EAGAIN或EWOULDBLOCK是正常的。

你bupt-is的吧?我也遇到这个问题了,换台电脑就好了

linux下C语言socket编程双机互发数据

这么专业的问题去专业的网站或搜索QQ群上问吧,百度里有空回答的怕没几个人知道。

这个问题很好办啦,服务器接受一个连接请求,然后开一个线程或者进程都可以,再在线程或者进程里面采用其他技术实现同时收发(比如I/O复用,比如非阻塞I/O)。客户端也可以采用I/O复用。

推荐资含尺拦料的话,《unix网络编程》这本书很好,公认的经典,当教科书用,这本书里有你想要的所有内容。

ps:你基础太差,多补补吧,别想一下吃困桐个胖子。

另外我这里正好有个例子满足你的要求,贴给你,自己写的,不是网上找的,用的是多进程加I/O复用技术:

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编程 怎样实现客户端之间互相通信

网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。

下面用Socket实现一个windows下的c语言socket通信例子,这里我们客户端传递一个字符串,服务器端进行接收。

【服务器端】

#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;

    }

    //创建Socket,使用TCP协议

    sListen=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (sListen == INVALID_SOCKET)

    {

WSACleanup();

printf(“socket() faild!\n”);

return;

    }

    //构建本地地址信息

    saServer.sin_family = AF_INET; //地址家族

    saServer.sin_port = htons(SERVER_PORT); //注意转化为网络字节序

    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); //关闭套接字

WSACleanup();

return;

    }

  

    //侦听连接请求

    ret = listen(sListen, 5);

    if (ret == SOCKET_ERROR)

    {

printf(“listen() faild! code:%d\n”, WSAGetLastError());

closesocket(sListen); //关闭套接字

return;

    }

  

    printf(“Waiting for client connecting!\n”);

    printf(“Tips: Ctrl+c to quit!\n”);

    //阻塞等待接受客户端连接

 while(1)//循环监听客户端,永远不停止,所以,在本项目中,我们没有心跳包。

 {

  length = sizeof(saClient);

 散码唤 sServer = accept(sListen, (struct sockaddr *)&saClient, &length);

  if (sServer == INVALID_SOCKET)

  {

   printf(“accept() faild! code:%d\n”, WSAGetLastError());

   closesocket(sListen); //关闭套接字

   WSACleanup();

   return;

  }

  char receiveMessage;

   nLeft = sizeof(receiveMessage);

  ptr = (char *)&receiveMessage;

  while(nLeft>0)

  {

   //接收数据

   ret = recv(sServer, ptr, 5000, 0);

   if (ret == SOCKET_ERROR)

   {

    printf(“recv() failed!\n”);

    return;

   }

   if (ret == 0) //客户端已经关冲凯闭连接

   {

    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;

   }

   //确认WinSock DLL支持版本2.2

   if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)

   {

WSACleanup();

printf(“Invalid WinSock version!\n”);

return;

   }

   //创建Socket,使用TCP协议

   sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if (sClient == INVALID_SOCKET)

   {

WSACleanup();

printf(“socket() failed!\n”);

return;

   }

   //构建服务器地址信息

   saServer.sin_family = AF_INET; //地址家族

   saServer.sin_port = htons(SERVER_PORT); //注意转化为网络节序

   saServer.sin_addr.S_un.S_addr = inet_addr(“192.168.1.127”);

   //连接服务器

   ret = connect(sClient, (struct sockaddr *)&saServer, sizeof(saServer));

   if (ret == SOCKET_ERROR)

   {

printf(“connect() failed!\n”);

closesocket(sClient); //关闭套接字

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); //关闭套接字

   WSACleanup();

}

网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该银铅搜Socket实现的。下面用Socket实现一个windows下的c语言socket通信例子,这里我们客户端传递一个字符串,服务器端进行接收。

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

【服务锋历激哗器端】

#include “stdafx.h”

#include

#include

#include

#define SERVER_PORT 5208 //侦听端口

void main()

关于linux c socket 阻塞的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 深入理解:Linux下C语言Socket阻塞机制 (linux c socket 阻塞)