文章目錄
- 前言
- 函數描述
- 代碼執行個體
- TCP伺服器為什麼調用listen
前言
根據TCP程式設計模型中我們可以看到之前的
socket
和
bind
接口是tcp伺服器在為接收用戶端的連結做準備,保證tcp的面向位元組流,面向連接配接的可靠通信服務正常進行。接下來的
listen
端口則為我們進行三次握手與用戶端進行連結的接口。
TCP程式設計模型如下
函數描述
-
#include <sys/socket.h>
-
int listen(int sockfd, int backlog);
- 函數功能:将套接字檔案描述符從主動轉為被動檔案描述符,然後用于被動監聽用戶端的連接配接
- 函數傳回值:成功傳回0,失敗傳回-1, errno被設定
-
參數:
a.
sockfd
表示socket建立的套接字檔案描述符
b.
backlog
指定隊列的容量
這個隊列用于記錄正在連接配接但是還沒有連接配接完成的用戶端,一般設定隊列的容量為2,3即可。隊列的最大容量需要小于30
代碼執行個體
#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);
}
return 0;
}