设置服务器监听,获取fd

大耗子 2020年02月29日 207次浏览

文章链接:https://codemouse.online/archives/2020-02-29-102714

设置服务器监听,获取fd

int SRV_create_listen_fd()
{

    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if(listenfd == -1)
    {
        ERR_PRINT("socket fail, listenfd:%d\n",listenfd);
        return false;
    }

    int on = 1;
    if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
    {
        ERR_PRINT("setsockopt fail\n");
        return false;
    }

    struct sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    //inet_pton(AF_INET, IP, &servaddr.sin_addr);
    

    if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof servaddr) < 0)
    {
        ERR_PRINT("bind fail\n"); 
        return false;
    }

    //listen端口
    if(listen(listenfd, LISTSIZE) < 0)
        ERR_PRINT("listen fail\n");

    return listenfd;
}

跨平台

#ifdef _WIN32
/*****************************************************************************
 函 数 名  : Service.init_win_listen
 功能描述  : 初始化监听的fd
            -1:创建套接字错误.
            -2:绑定错误
            -3:监听错误
            win特有:
            -4:WSA初始化错误
 输入参数  : const char *ip  
             int port        
 输出参数  : 无
 返 回 值  : sockfd Service::
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2020年5月25日
    作    者   : codeMouse
    修改内容   : 新生成函数

*****************************************************************************/
int Service::initListen(const char *ip, int port)
{
    //初始化WSA
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	if (WSAStartup(sockVersion, &wsaData) != 0)
	{
        printf("init WSA fail!\n");
		return -4;
	}

	//创建套接字
	SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (slisten == INVALID_SOCKET)
	{
		printf("socket error !\n");
		return -1;
	}

	//绑定IP和端口
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);
	sin.sin_addr.s_addr = inet_addr(ip);
    //sin.sin_addr.s_addr = INADDR_ANY;
	if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
	{
		printf("bind error !\n");
		closesocket(slisten);
        return -2;
        
	}

	//开始监听
	if (listen(slisten, 10) == SOCKET_ERROR)
	{
		printf("listen error !\n");
		closesocket(slisten);
		return -3;
	}
	printf("listen addr:%s  port:%d\n", ip,port);
    listenfd = slisten;
    return 1;
}
#else
int Service::initListen(const char *ip, int port)
{
    //1.creat socket
    int slisten = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(fd < 0){
        perror("creat socket error\n");
        return -1;
    }

    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);
    sin.sin_addr.s_addr = inet_addr(ip);//INADDR_ANY
    
    //2.bind

    if(bind(slisten,(struct sockaddr*)&sin,sizeof(sin)) < 0){
        perror("bind error\n");
        close(slisten);
        return -2;
    }
   
    //3.listen

    if(listen(slisten,10) < 0){
        perror("listen error\n");
        close(slisten);
        return -3;
    }
    listenfd = slisten;

    return 1;
}
#endif

获取客户端fd

void * SRV_accept_process(void *args)
{
    int listenfd = atoi((char *)args);
    int clifd = 0;
    // 客户端参数
    struct sockaddr_in tCliaddr;
	socklen_t 		   tCliaddlen;
	tCliaddlen = sizeof(tCliaddr);

    //int clifd = accept(listenfd, NULL, NULL);

ACCEPT:
    clifd = accept(listenfd,(struct sockaddr*)(&tCliaddr), &tCliaddlen);
	if(clifd == -1)
	{
		if(errno==EINTR)
		{
			goto ACCEPT;
		}
		else
		{
			ERR_PRINT("accept fail\n");
            return NULL;
		}
	}
    
    DBG_PRINT("accept new client(%d):%s:%d\n", clifd, inet_ntoa(tCliaddr.sin_addr),tCliaddr.sin_port);

    return NULL;
}