📜  接受系统调用

📅  最后修改于: 2021-05-26 02:20:33             🧑  作者: Mango

具有基于连接的套接字类型( SOCK_STREAM,SOCK_SEQPACKET )的accept()系统调用。它为侦听套接字sockfd提取未决连接队列中的第一个连接请求,创建一个新的已连接套接字,并返回引用该套接字的新文件描述符。新创建的套接字未处于侦听状态。原始套接字sockfd不受此调用的影响。
句法:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 
  • sockfd:参数sockfd是已使用socket()创建的套接字,已使用bind ()绑定到本地地址,并在listen ()之后监听连接。
  • addr :参数addr是指向sockaddr结构的指针。如通信层所知,该结构用对等套接字的地址填充。返回的地址的确切格式addr由套接字的地址族确定。当addr为NULL时,
    什么都没填;在这种情况下,不使用addrlen ,并且也应为NULL。
  • addrlenaddrlen参数是一个值结果参数:调用者必须对其进行初始化,以包含addr指向的结构的大小(以字节为单位);返回时,它将包含对等地址的实际大小。
  • 返回值:成功时,这些系统调用将返回一个非负整数,该整数是已接受套接字的文件描述符。如果出错,则返回-1,并正确设置errno

如果提供的缓冲区太小,返回的地址将被截断;否则,返回的地址将被截断。在这种情况下,addrlen将返回一个大于提供给调用的值。
如果队列上没有待处理的连接,并且套接字未标记为非阻塞,则accept ()会阻塞调用者,直到存在连接为止。如果套接字被标记为非阻塞并且队列上没有挂起的连接,则accept ()失败,错误为EAGAINEWOULDBLOCK

// C program to show accept system call is blocking call
#include                                                                                                                                        
#include                                                                                                                                    
#include                                                                                                                                   
#include                                                                                                                                   
#include                                                                                                                                       
#define BACKLOG 3                                                                                                                                            
  
// Driver program                                                                                                                                                            
int main()                                                                                                                                               
{                                                                                                                                                            
        struct sockaddr_in my_addr, peer_addr;                                                                                                               
        socklen_t peer_addr_size;                                                                                                                            
        int sd, b, l, acc;                                                                                                                                   
        my_addr.sin_family = AF_INET;
          
        // Creating socket                                                                                                                       
        sd = socket(AF_INET, SOCK_STREAM, 0); 
          
        // Binding                                                                                                               
        b = bind(sd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr_in));                                                                               
        if(b > 0)                                                                                                                                            
                printf("Binded Successfully\n");                                                                                                             
        else                                                                                                                                                
                printf("Binding Error\n"); 
        // Listening                                                                                                                 
        l = listen(sd, BACKLOG);                                                                                                                             
        if(l > 0)                                                                                                                                            
                printf("Listening...\n");                                                                                                                    
        else                                                                                                                                                
                printf("Not listening..\n");                                                                                                                 
        peer_addr_size = sizeof(struct sockaddr_in); 
          
        // Accept system call                                                                                                    
        acc = accept(sd, (struct sockaddr *)&peer_addr, &peer_addr_size);                                                                                    
        if(acc > 0)                                                                                                                                      
                printf("Accepted\n");                                                                                                                        
        else                                                                                                                                                
                printf("Not accepted\n");                                                                                                                    
}                                           
  
                                  

输出:

Binding Successfully
Listening.. 

accept()调用中的错误

  1. EAGAIN或EWOULDBLOCK:套接字被标记为非阻塞,并且不存在可以接受的连接。 POSIX.1-2001和POSIX.1-2008允许在这种情况下返回任一错误,并且不需要这些常量具有相同的值,因此可移植应用程序应检查这两种可能性。
  2. EBADF: sockfd不是打开的文件描述符。
  3. ECONNABORTED:连接已中止。
  4. EFAULT: addr参数不在用户地址空间的可写部分中。
  5. EINTR:系统调用被有效连接到达之前捕获的信号中断;参见signal(7)。
  6. EINVAL:套接字未监听连接,或者addrlen无效(例如,为负)。
  7. EINVAL: (accept4())标志中的无效值。
  8. EMFILE:已达到打开文件描述符数量的每个进程限制。
  9. ENFILE:已达到系统范围内打开文件总数的限制。
  10. ENOBUFS,ENOMEM:可用内存不足。这通常意味着记忆
    分配受套接字缓冲区限制的限制,而不是受系统内存的限制。
  11. ENOTSOCK:文件描述符sockfd不引用套接字。
  12. EOPNOTSUPP:所引用的套接字不是SOCK_STREAM类型。
  13. EPROTO:协议错误。
想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。