C语言阻塞网络的原因是什么?

C语言中,阻塞网络操作是指程序在执行网络I/O时会暂停(阻塞)在那里,直到操作完成。

在C语言中,阻塞网络编程是一种常见的编程方式,它使得程序在执行某些操作时会暂停执行,直到特定条件满足或事件发生,以下是对C语言中阻塞网络编程的详细解释:

C 阻塞网络

阻塞网络编程的基本概念

阻塞网络编程指的是程序在执行网络I/O操作(如读取数据、发送数据等)时,如果所需条件不满足(如数据未到达、连接未建立等),程序会暂停执行,等待条件满足后再继续执行,这种编程方式在某些场景下非常直观和易于理解,但也可能因为长时间等待而导致程序效率低下。

常见的阻塞函数

1、sleep()函数:使程序暂停执行一段时间,单位为秒。sleep(5);会使程序暂停执行5秒。

2、read()函数:从文件或输入设备读取数据,当没有数据可读时,程序将阻塞在此处等待数据准备就绪。

3、write()函数:将数据写入文件或输出设备,如果写入的数据无法立即处理,程序将阻塞在此处等待直到数据处理完成。

4、accept()函数:用于接受传入的网络连接请求,如果没有新的连接请求到达,则程序将阻塞在此处等待新的连接请求。

C 阻塞网络

5、recv()函数:用于从网络套接字接收数据,如果没有数据可接收,则程序将阻塞在此处等待数据到达。

阻塞网络编程的示例代码

以下是一个使用阻塞方式进行网络通信的简单示例,展示了客户端如何连接到服务器并发送/接收数据:

服务器端代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define PORT 8080
int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};
    char hello = "Hello from server";
    // 创建socket文件描述符
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }
    // 强制附加socket到端口8080
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);
    // 绑定socket到端口8080
    if (bind(server_fd, (struct sockaddr )&address, sizeof(address))<0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    if ((new_socket = accept(server_fd, (struct sockaddr )&address, (socklen_t)&addrlen))<0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }
    read(new_socket, buffer, 1024);
    printf("%s
",buffer );
    send(new_socket , hello , strlen(hello) , 0 );
    printf("Hello message sent
");
    return 0;
}

客户端代码

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define PORT 8080
int main(int argc, char const argv[]) {
    struct sockaddr_in serv_addr;
    int sock = 0;
    char hello = "Hello from client";
    char buffer[1024] = {0};
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("
 Socket creation error 
");
        return -1;
    }
  
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
     
    if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {
        printf("
Invalid address/ Address not supported 
");
        return -1;
    }
  
    if (connect(sock, (struct sockaddr )&serv_addr, sizeof(serv_addr)) < 0) {
        printf("
Connection Failed 
");
        return -1;
    }
    send(sock , hello , strlen(hello) , 0 );
    printf("Hello message sent
");
    read(sock , buffer, 1024);
    printf("%s
",buffer );
    return 0;
}

在这个示例中,服务器端首先创建一个socket,然后绑定到本地地址和端口上,并开始监听客户端的连接请求,当有客户端连接时,服务器接受连接并接收客户端发送的数据,然后发送响应给客户端,客户端则创建一个socket,连接到服务器,并发送数据给服务器,然后接收服务器的响应。

阻塞与非阻塞的区别

1、阻塞模式:在阻塞模式下,调用某个函数(如recv())后,如果数据没有立即可用,函数不会返回,整个进程会被挂起,直到数据到来或者发生错误,这种方式简化了编程模型,因为不需要额外处理异步事件通知和数据缓冲。

2、非阻塞模式:在非阻塞模式下,即使没有数据可读或可写,函数也会立即返回,不会阻塞进程的执行,这要求程序员必须检查返回值以确定操作是否成功,并在适当的时候重试操作,非阻塞模式适用于需要高并发处理大量网络连接的场景,因为它允许单个线程或进程同时管理多个连接,而不必为每个连接分配一个线程。

C 阻塞网络

FAQs

Q1: 阻塞网络编程中,如何避免死锁问题?

A1: 在阻塞网络编程中,为了避免死锁问题,应确保正确地使用同步机制(如互斥锁、条件变量等),避免循环等待资源的情况发生,还可以通过设置超时时间、使用非阻塞I/O等方式来减少死锁的风险。

Q2: 阻塞网络编程与非阻塞网络编程相比,有哪些优缺点?

A2: 阻塞网络编程的优点在于编程模型简单直观,易于理解和实现,它的缺点是在处理大量并发连接时效率较低,因为每个连接都需要占用一个线程或进程资源,相比之下,非阻塞网络编程虽然编程模型相对复杂,但能够更有效地利用系统资源,提高并发处理能力。

原创文章,作者:未希,如若转载,请注明出处:https://www.kdun.com/ask/1608663.html

本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。

(0)
未希未希
上一篇 2025-03-02 19:22
下一篇 2025-03-02 19:29

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

产品购买 QQ咨询 微信咨询 SEO优化
分享本页
返回顶部
云产品限时秒杀。精选云产品高防服务器,20M大带宽限量抢购 >>点击进入