日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

C语言网络编程:accept函数详解

發布時間:2023/11/27 生活经验 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言网络编程:accept函数详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

          • 前言
          • 函數描述
          • 代碼實例
          • 如何得到客戶端的IP 和 端口號

前言

當使用tcp服務器使用socket創建通信文件描述符,bind綁定了文件描述符,服務器ip和端口號,listen將服務器端的主動描述符轉為被動描述符進行監聽之后,接口accept通過三次握手與客戶端建立連接

TCP 編程模型如下:


函數描述
  • #include <sys/socket.h>
  • int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • 函數功能:
    被動監聽客戶端發起的tcp連接請求,三次握手后連接建立成功。客戶端connect函數請求發起連接。
    連接成功后服務器的tcp協議會記錄客端的ip和端口,如果是跨網通信,記錄ip的就是客戶端所在路由器的公網ip
  • 返回值:
    成功:返回一個通信描述符,專門用于與連接成功的客戶端進行通信。
    失敗:返回-1 ,并設置errno
  • 函數參數:
    a. sockfd 已經被listen轉為了被動描述符的“套接字文件描述符”,專門用于客戶端的監聽,入股sockfs沒有被listen函數轉為被動描述符,則accept是無法將其用來監聽客戶端連接的。
    套接字文件描述符默認是阻塞的,即如果沒有客戶端請求連接的時候,此時accept會阻塞,直到有客戶端連接;如果不想套接字文件描述符阻塞,則可以創建套接字 socket函數 時指定typeSOCK_NOBLOCK
    b. addrlen表示第二個參數addr的大小,不顧要求給定地址
    c. addr: 用于記錄發起連接請求的那個客戶端的IP端口
    建立連接時服務器的TCP協議會自動解析客戶端發來的數據包,從中獲取客戶端的IP和端口號
    這里如果服務器應用層需要用到客戶端的 IP和端口號,可以給accept指定第二個參數addr,以獲取TCP鏈接時的客戶端ip和端口號;如果服務器應用層不需要,則寫NULL即可
    addr的結構體類型為 struct sockaddr,在listen函數詳解中我們有介紹過,由于這個結構體用起來不是非常方便,我們需要定義struct sockaddr_in結構體來使得sockaddr結構體操作更為便捷。具體使用如下:
    struct sockaddr_in naddr = {0};int nsize = sizeof(naddr);
    int cfd = accept(sockfd, (struct sockaddr *)&naddr, &nsize);
    
代碼實例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>void print_err(char *str, int line, int err_no) {printf("%d, %s :%s\n",line,str,strerror(err_no));_exit(-1);
}int main()
{int skfd = -1, ret = -1;skfd = socket(AF_INET, SOCK_STREAM, 0);if ( -1 == skfd) {print_err("socket failed",__LINE__,errno);}struct sockaddr_in addr;addr.sin_family = AF_INET; //設置tcp協議族addr.sin_port = 6789; //設置端口號addr.sin_addr.s_addr = inet_addr("192.168.102.169"); //設置ip地址ret = bind(skfd, (struct sockaddr*)&addr, sizeof(addr));if ( -1 == ret) {print_err("bind failed",__LINE__,errno);}/*將套接字文件描述符從主動轉為被動文件描述符,然后用于被動監聽客戶端的連接*/ret = listen(skfd, 3);if ( -1 == ret ) {print_err("listen failed", __LINE__, errno);}/*被動監聽客戶端發起的tcp連接請求,三次握手后連接建立成功*/int cfd = -1;struct sockaddr_in caddr = {0}; //為應用層獲取客戶端的IP和端口號int csize = 0;cfd = accept(skfd, (struct sockaddr*)&caddr, &csize);if (-1 == cfd) {print_err("accept failed", __LINE__, errno);}return 0;
}
如何得到客戶端的IP 和 端口號

比如程序中想要打印客戶端的ip和端口號,這里就需要使用到ntohsinet_ntoa函數進行端序轉換,因為客戶端的端口和ip是服務器的TCP協議,從客戶端發送端網絡數據包中提取出來,網絡數據包的端序屬于網絡端序,主機接收到數據后如果想要使用的話,就必須從網絡端序轉為主機端序。

舉例如下:

struct sockaddr_in caddr = {0};int csize = sizeof(caddr);
cfd = accept(sockfd, (struct sockaddr *)&caddr, &csize);printf("cport = %d, caddr = %s\n", ntohs(caddr.sin_port),inet_ntoa(caddr.sin_addr));

總結

以上是生活随笔為你收集整理的C语言网络编程:accept函数详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。