libmodbus TCP 及网络编程select函数(FD_ZERO,FD_SET,FD_CLR,FD_ISSET)

1 篇文章 0 订阅
1 篇文章 0 订阅

最近项目中用到libmodbus TCP通讯的过程处理数据,原项目程序无法实现断网重连,现在要求只要的有新的连接,就主动断掉上一次的连接。
也是第一次用libmodbus TCP库。学习过程及代码如下:

基础知识:

SELECT 函数用于在非阻塞中,当一个套接字或者一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型。
函数原型:
libmodbus TCP通信demo测试

 #include <sys/time.h>
 #include <unistd.h>
 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

第一个参数:int nfds—>是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1

第二个参数:fd_set *readfds---->用来检查一组可读性的文件描述符。

第三个参数:fd_set *writefds---->用来检查一组可写性的文件描述符。

第四个参数:fd_set *exceptfds---->用来检查文件文件描述符是否异常

第五个参数:sreuct timeval *timeout—>是一个时间结构体,用来设置超时时间

timeout:最多等待时间,对阻塞操作则为NULL

select函数的返回值
负值:select错误
正值:表示某些文件可读或可写
0:等待超时,没有可读写或错误的文件

阻塞:
当某个事件或者任务在执行过程中,它发出一个请求操作,但是由于该请求操作的条件不满足,那么就会一直在那等待,直至满足条件;
非阻塞:
当某个事件或者任务在执行过程中,它发出一个请求操作,如果该操作需要的条件不满足,会立即返回一个标志信息告知条件不满足,不会一直等待下去。
这里在补充一个同步和异步的关系。
同步和异步的重在与多个任务的执行过程,一个任务的执行是否导致整个流程暂时等待。
阻塞和非阻塞的重点在发出一个请求操作时,进行操作的条件是否会返回一个标志信息告知。
什么是套接字?
网络套接字又叫网际插座,又叫Internet Socket。
在网络中,套接字扮演的角色正如插座一样,它是一个端点,可以与网络中的其他套接字建立连接。
微软计算机词典对于套接字给出的解释如下:

Socket is an identifier for a particular service on a particular node on a network. The socket consists of a node address and a port number, which identifies the service.
套接字是一个位于网络中特定节点的服务所具有的标识符。套接字包含一个节点地址和一个端口号,用来标识这一服务

在网络中,IP地址可以唯一确定一台主机,但准确来说,网络通讯的双方不是主机,而是运行在主机上的进程,这样的酒需要进一步确定主机中的哪个进程需要网络通讯,因此,除IP地址之外,还需要端口来唯一确定主机的通讯过程。
总结:IP地址和端口号构成了一个网络中的唯一标识符,及套接字。

套接字允许两个进行通讯,这个进程可以在同一台机器上,也可能在不同机器上运行。
套接字是使用标准Unix文件描述符来与其他计算机进行通讯的一种方式。

在Unix操作系统中,每一个读写操作都是通过读写文件描述符来完成的。一个文件描述符就是一个与打开的文件相关联的整数,它可以是一个网络连接,一个文本文件,一个终端或者其他东西。

套接字类型:流套接字(TCP),数据包套接字(UDP),原始套接字

示例一:服务端与客户端连接通信,断网无法重连:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
 
#include "modbus.h"
#include "modbus-tcp.h"
#include "modbus-version.h"
 
#if defined(_WIN32)
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
 
#define NB_CONNECTION    5
 
//线圈地址数据的定义
const uint16_t UT_BITS_ADDRESS = 0x13;
const uint16_t UT_BITS_NB = 0x25;
const uint8_t UT_BITS_TAB[] = { 0xCD, 0x6B, 0xB2, 0x0E, 0x1B };
//离散量输入寄存器地址数据的定义
const uint16_t UT_INPUT_BITS_ADDRESS = 0xC4;
const uint16_t UT_INPUT_BITS_NB = 0x16;
const uint8_t UT_INPUT_BITS_TAB[] = { 0xAC, 0xDB, 0x35 };
//读保持寄存器地址数据的定义
const uint16_t UT_REGISTERS_ADDRESS = 0x6B;
/* Raise a manual exception when this adress is used for the first byte */
const uint16_t UT_REGISTERS_ADDRESS_SPECIAL = 0x6C;
const uint16_t UT_REGISTERS_NB = 0x3;
const uint16_t UT_REGISTERS_TAB[] = { 0x022B, 0x0001, 0x0064 };
/* If the following value is used, a bad response is sent.
   It's better to test with a lower value than
   UT_REGISTERS_NB_POINTS to try to raise a segfault. */
const uint16_t UT_REGISTERS_NB_SPECIAL = 0x2;
//输入寄存器地址数据定义
const uint16_t UT_INPUT_REGISTERS_ADDRESS = 0x08;
const uint16_t UT_INPUT_REGISTERS_NB = 0x1;
const uint16_t UT_INPUT_REGISTERS_TAB[] = { 0x000A };
 
modbus_t *ctx = NULL;
int server_socket;
modbus_mapping_t *mb_mapping;
 
static void close_sigint(int dummy)
{
    close(server_socket);
    modbus_free(ctx);
    modbus_mapping_free(mb_mapping);
 
    exit(dummy);
}
 
 
int main(void)
{
    int master_socket;
    int rc;
    fd_set refset;
    fd_set rdset;
 
    /* Maximum file descriptor number */
    int fdmax;
 
    ctx = modbus_new_tcp("127.0.0.1", 502);
 
    //new一个modbus的映射空间
    mb_mapping = modbus_mapping_new(
        UT_BITS_ADDRESS + UT_BITS_NB,//读线圈
        UT_INPUT_BITS_ADDRESS + UT_INPUT_BITS_NB,//读离散量输入
        UT_REGISTERS_ADDRESS + UT_REGISTERS_NB,//读保持寄存器
        UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB);//读输入寄存器
    if (mb_mapping == NULL)
    {
        fprintf(stderr, "Failed to allocate the mapping: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }
 
    /** 初始化离散量输入寄存器 **/
    modbus_set_bits_from_bytes(mb_mapping->tab_input_bits,UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB,UT_INPUT_BITS_TAB);
 
    /** 初始化输入寄存器 **/
    for (i=0; i < UT_INPUT_REGISTERS_NB; i++)
    {
        mb_mapping->tab_input_registers[UT_INPUT_REGISTERS_ADDRESS+i] =UT_INPUT_REGISTERS_TAB[i];
    }
    /**初始化读保持寄存器**/
    for(i=0; i<UT_REGISTERS_NB; i++)
    {
        mb_mapping->tab_registers[UT_REGISTERS_ADDRESS+i]=UT_REGISTERS_TAB[i];
    }
 
    server_socket = modbus_tcp_listen(ctx, NB_CONNECTION);
 
    signal(SIGINT, close_sigint);
 
    /* Clear the reference set of socket */
    FD_ZERO(&refset);
    /* Add the server socket */
    FD_SET(server_socket, &refset);
 
    /* Keep track of the max file descriptor */
    fdmax = server_socket;
 
    for (;;)
    {
        rdset = refset;
        if (select(fdmax+1, &rdset, NULL, NULL, NULL) == -1)
        {
            perror("Server select() failure.");
            close_sigint(1);
        }
 
        /* Run through the existing connections looking for data to be
         * read */
        for (master_socket = 0; master_socket <= fdmax; master_socket++)
        {
 
            if (FD_ISSET(master_socket, &rdset))
            {
                if (master_socket == server_socket)
                {
                    /* A client is asking a new connection */
                    socklen_t addrlen;
                    struct sockaddr_in clientaddr;
                    int newfd;
 
                    /* Handle new connections */
                    addrlen = sizeof(clientaddr);
                    memset(&clientaddr, 0, sizeof(clientaddr));
                    newfd = accept(server_socket, (struct sockaddr *)&clientaddr, &addrlen);
                    if (newfd == -1)
                    {
                        perror("Server accept() error");
                    }
                    else
                    {
                        FD_SET(newfd, &refset);
                        if (newfd > fdmax)
                        {
                            /* Keep track of the maximum */
                            fdmax = newfd;
                        }
                        printf("New connection from %s:%d on socket %d\n", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port, newfd);
                    }
                }
                else
                {
                    /* An already connected master has sent a new query */
                    uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
                    int data = 0;
                    int address=0;
 
                    modbus_set_socket(ctx, master_socket);
                    rc = modbus_receive(ctx, query);
 
                    address =  (query[header_length+1]<<8) + query[header_length+2];
                    if(query[header_length] == 0x06 )
                    {
                        //to do 功能码 写保持寄存器
                    }
 
                    if (rc != -1)
                    {
                        modbus_reply(ctx, query, rc, mb_mapping);
                    }
                    else
                    {
                        /* Connection closed by the client, end of server */
                        printf("Connection closed on socket %d\n", master_socket);
                        close(master_socket);
 
                        /* Remove from reference set */
                        FD_CLR(master_socket, &refset);
 
                        if (master_socket == fdmax)
                        {
                            fdmax--;
                        }
                    }
                }
            }
        }
    }
 
    return 0;
}

示例二:服务端与客户端连接通信,断网可以重连,一对多(可以与多个客户端通讯):

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
 
#include "modbus.h"
#include "modbus-tcp.h"
#include "modbus-version.h"
 
#if defined(_WIN32)
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
 
#define NB_CONNECTION    5
 
//线圈地址数据的定义
const uint16_t UT_BITS_ADDRESS = 0x13;
const uint16_t UT_BITS_NB = 0x25;
const uint8_t UT_BITS_TAB[] = { 0xCD, 0x6B, 0xB2, 0x0E, 0x1B };
//离散量输入寄存器地址数据的定义
const uint16_t UT_INPUT_BITS_ADDRESS = 0xC4;
const uint16_t UT_INPUT_BITS_NB = 0x16;
const uint8_t UT_INPUT_BITS_TAB[] = { 0xAC, 0xDB, 0x35 };
//读保持寄存器地址数据的定义
const uint16_t UT_REGISTERS_ADDRESS = 0x6B;
/* Raise a manual exception when this adress is used for the first byte */
const uint16_t UT_REGISTERS_ADDRESS_SPECIAL = 0x6C;
const uint16_t UT_REGISTERS_NB = 0x3;
const uint16_t UT_REGISTERS_TAB[] = { 0x022B, 0x0001, 0x0064 };
/* If the following value is used, a bad response is sent.
   It's better to test with a lower value than
   UT_REGISTERS_NB_POINTS to try to raise a segfault. */
const uint16_t UT_REGISTERS_NB_SPECIAL = 0x2;
//输入寄存器地址数据定义
const uint16_t UT_INPUT_REGISTERS_ADDRESS = 0x08;
const uint16_t UT_INPUT_REGISTERS_NB = 0x1;
const uint16_t UT_INPUT_REGISTERS_TAB[] = { 0x000A };
 
modbus_t *ctx = NULL;
int server_socket;
modbus_mapping_t *mb_mapping;
 
static void close_sigint(int dummy)
{
    close(server_socket);
    modbus_free(ctx);
    modbus_mapping_free(mb_mapping);
 
    exit(dummy);
}
 
 
int main(void)
{
    int master_socket;
    int rc;
    fd_set refset;
    fd_set rdset;
 
    /* Maximum file descriptor number */
    int fdmax;
 
    ctx = modbus_new_tcp("127.0.0.1", 502);
 
    //new一个modbus的映射空间
    mb_mapping = modbus_mapping_new(
        UT_BITS_ADDRESS + UT_BITS_NB,//读线圈
        UT_INPUT_BITS_ADDRESS + UT_INPUT_BITS_NB,//读离散量输入
        UT_REGISTERS_ADDRESS + UT_REGISTERS_NB,//读保持寄存器
        UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB);//读输入寄存器
    if (mb_mapping == NULL)
    {
        fprintf(stderr, "Failed to allocate the mapping: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }
 
    /** 初始化离散量输入寄存器 **/
    modbus_set_bits_from_bytes(mb_mapping->tab_input_bits,UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB,UT_INPUT_BITS_TAB);
 
    /** 初始化输入寄存器 **/
    for (i=0; i < UT_INPUT_REGISTERS_NB; i++)
    {
        mb_mapping->tab_input_registers[UT_INPUT_REGISTERS_ADDRESS+i] =UT_INPUT_REGISTERS_TAB[i];
    }
    /**初始化读保持寄存器**/
    for(i=0; i<UT_REGISTERS_NB; i++)
    {
        mb_mapping->tab_registers[UT_REGISTERS_ADDRESS+i]=UT_REGISTERS_TAB[i];
    }
 
    server_socket = modbus_tcp_listen(ctx, NB_CONNECTION);
 
    signal(SIGINT, close_sigint);
 
    /* Clear the reference set of socket */
    FD_ZERO(&refset);
    /* Add the server socket */
    FD_SET(server_socket, &refset);
 
    /* Keep track of the max file descriptor */
    fdmax = server_socket;
 
    for (;;)
    {
        rdset = refset;
        if (select(fdmax+1, &rdset, NULL, NULL, NULL) == -1)
        {
            perror("Server select() failure.");
            close_sigint(1);
        }
 
        /* Run through the existing connections looking for data to be
         * read */
        for (master_socket = 0; master_socket <= fdmax; master_socket++)
        {
 
            if (FD_ISSET(master_socket, &rdset))
            {
                if (master_socket == server_socket)
                {
                    /* A client is asking a new connection */
                    socklen_t addrlen;
                    struct sockaddr_in clientaddr;
                    int newfd;
 
                    /* Handle new connections */
                    addrlen = sizeof(clientaddr);
                    memset(&clientaddr, 0, sizeof(clientaddr));
                    newfd = accept(server_socket, (struct sockaddr *)&clientaddr, &addrlen);
                    if (newfd == -1)
                    {
                        perror("Server accept() error");
                    }
                    else
                    {
                        FD_SET(newfd, &refset);
                        if (newfd > fdmax)
                        {
                            /* Keep track of the maximum */
                            fdmax = newfd;
                        }
                        printf("New connection from %s:%d on socket %d\n", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port, newfd);
                    }
                }
                else
                {
                    /* An already connected master has sent a new query */
                    uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
                    int data = 0;
                    int address=0;
 
                    modbus_set_socket(ctx, master_socket);
                    rc = modbus_receive(ctx, query);
 
                    address =  (query[header_length+1]<<8) + query[header_length+2];
                    if(query[header_length] == 0x06 )
                    {
                        //to do 功能码 写保持寄存器
                    }
 
                    if (rc != -1)
                    {
                        modbus_reply(ctx, query, rc, mb_mapping);
                    }
                    else
                    {
                        /* Connection closed by the client, end of server */
                        printf("Connection closed on socket %d\n", master_socket);
                        close(master_socket);
 
                        /* Remove from reference set */
                        FD_CLR(master_socket, &refset);
 
                        if (master_socket == fdmax)
                        {
                            fdmax--;
                        }
                    }
                }
            }
        }
    }
 
    return 0;
}

示例三:服务端与客户端连接通信,断网可以重连,一对一,只接收最新客户端连接通讯:

             // 传输模式TCP		
			ctx = modbus_new_tcp(m_szIp1, m_ntcp_port);	
			if (ctx == NULL)
			{
				fprintf(stderr, "Unable to allocate libmodbus context\n");
				bConnect = false;
			
			}


			unsigned int mb_start_bits = 0; unsigned int mb_nb_bits = 0;
			unsigned int mb_start_input_bits = 0; unsigned int mb_nb_input_bits = 0;
			unsigned int mb_start_registers = 0;unsigned int mb_nb_registers = 0;
			unsigned int mb_start_input_registers = 0; unsigned int mb_nb_input_registers = 0;

			


			if (protocol->m_nYxFun==0x01)
			{
				mb_start_bits = protocol->m_nYxStartAddr;
				mb_nb_bits = protocol->m_nYx_nb;
			}
			if (protocol->m_nYxFun==0x02)
			{
				mb_start_input_bits = protocol->m_nYxStartAddr;
				mb_nb_input_bits = protocol->m_nYx_nb;
			}
			if (protocol->m_nYcFun==0x03)
			{
				mb_start_registers = protocol->m_nYcStartAddr;
				mb_nb_registers += protocol->m_nYc_nb*2;
			}
			if (protocol->m_nYcFun==0x04)
			{
				mb_start_input_registers = protocol->m_nYcStartAddr;
				mb_nb_input_registers +=protocol->m_nYc_nb*2;
			}

			if (protocol->m_nDdFun==0x03)
			{
				mb_start_registers = protocol->m_nDdStartAddr;
				mb_nb_registers +=protocol->m_nDd_nb*2;
			}
			if (protocol->m_nDdFun==0x04)
			{
				mb_start_input_registers = protocol->m_nDdStartAddr;
				mb_nb_input_registers +=protocol->m_nDd_nb*2;
			}
			 //new一个modbus的映射空间
			mb_mapping = modbus_mapping_new(
						mb_start_bits + mb_nb_bits,//读线圈
						mb_start_input_bits + mb_nb_input_bits,//读离散量输入
						mb_start_registers + mb_nb_registers,//读保持寄存器
						mb_start_input_registers + mb_nb_input_registers);//读输入寄存器
			//mb_mapping = modbus_mapping_new_start_address(mb_start_bits,mb_nb_bits,mb_start_input_bits,mb_nb_input_bits,mb_start_registers,mb_nb_registers,mb_start_input_registers,mb_nb_input_registers);
			if (mb_mapping == NULL) 
			{
				fprintf(stderr, "Failed to allocate the mapping: %s\n",
					modbus_strerror(errno));
				modbus_free(ctx);
				return -1;
			}

      

			

         
		
			int rc;
			fd_set refset;
			fd_set rdset;
		
			/* Maximum file descriptor number */
			int fdmax;
			
        
			server_socket = modbus_tcp_listen(ctx, NB_CONNECTION);
			signal(SIGINT, close_sigint);
			 /* Clear the reference set of socket */
			FD_ZERO(&refset);
			/* Add the server socket */
			FD_SET(server_socket, &refset);
		
			/* Keep track of the max file descriptor */
			fdmax = server_socket;
			
	

			for (;;) 
			{
				//Zx add code
				rdset = refset;	
				int ret = select(fdmax+1, &rdset, NULL, NULL, NULL);  //fdmax+1 参数是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1
				
				if (ret == -1)
				{					
					printf("Server select() failure.");
					close_sigint(1);
				}
				else
				{
			
					printf("Server select() %d     fdmax = %d    rdset[0] = %d   rdset[1] = %d    rdset[2] = %d   rdset[3] = %d     \n", ret,fdmax, rdset.fd_array[0], rdset.fd_array[1], rdset.fd_array[2] ,rdset.fd_array[3]);
				}
			
		
				/** Run through the existing connections looking for data to be
				 * read */
					
				
		 
					if (FD_ISSET( rdset.fd_array[0], &rdset))
					{
					
						if ( rdset.fd_array[0] == server_socket)
						{							
							/* A client is asking a new connection */
							socklen_t addrlen;
							struct sockaddr_in clientaddr;
							int newfd;
		 
							/* Handle new connections */
							addrlen = sizeof(clientaddr);
							memset(&clientaddr, 0, sizeof(clientaddr));
							newfd = accept(server_socket, (struct sockaddr *)&clientaddr, &addrlen);
							/*Record the first time a link descriptor*/
							if(m_bNewfd)
							{
                                    m_iNewfd = newfd;
								    m_bNewfd = false;
							}

							if(m_iNewfd != newfd )
							{								
								/* Connection closed by the client, end of server */							
								close(m_iNewfd);
		 
								/* Remove from reference set */
								FD_CLR(m_iNewfd, &refset);
							    m_iNewfd = newfd;
							    printf(" accept   -->Connection closed on socket %d\n", m_iNewfd);
							}

							if (newfd == -1)
							{
								printf("Server accept() error");
							}
							else
							{								
							
								FD_SET(newfd, &refset);
								if (newfd > fdmax)
								{
									/* Keep track of the maximum */
									fdmax = newfd;
								}
								printf("New connection from %s:%d on socket %d\n", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port, newfd);
							}
						}
						else
						{
							/* An already connected master has sent a new query */
							uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];						
		 
							modbus_set_socket(ctx, m_iNewfd);
							rc = modbus_receive(ctx, query);	 
							
							
							if (rc != -1)
							{
								//zx add processing data
								bConnect = true;
								modbus_reply(ctx, query, rc, mb_mapping);
								uint8_t* temp_rec_buf;
								uint8_t* temp_send_buf;
								int  temp_nSendLen =0;
								int  temp_nRecLen =0;

								BYTE ok_send_buf[300];
								BYTE ok_recv_buf[300];
								ZeroMemory(ok_send_buf, sizeof(ok_send_buf));
								ZeroMemory(ok_recv_buf, sizeof(ok_recv_buf));

								temp_nSendLen=modbus_get_sentlengh();
								temp_send_buf = modbus_get_sentbuf();
								temp_nRecLen=modbus_get_recvlengh();
								temp_rec_buf = modbus_get_recvbuf();
								memcpy(ok_send_buf, temp_send_buf, temp_nSendLen);
								memcpy(ok_recv_buf, temp_rec_buf, temp_nRecLen);

								m_pShow->SaveCharIn(ok_recv_buf,temp_nRecLen,10);
								m_pShow->SaveCharOut(ok_send_buf,temp_nSendLen,9);
								
								
									
							}
							else
							{
								//bConnect = false;
								/* Connection closed by the client, end of server */
								printf("Connection closed on socket %d\n", m_iNewfd);
								close(m_iNewfd);
		 
								/* Remove from reference set */
								FD_CLR(m_iNewfd, &refset);		 
						
							}
							
						}
					}
			     }
				

附录

libmodbus协议介绍中文完整带书签版:https://download.csdn.net/download/u011251940/11341158

下载libmodbus源码包:https://www.libmodbus.org/releases/libmodbus-3.0.6.tar.gz

libmodbus使用手册:https://libmodbus.org/docs/v3.0.6/

libmodbus调试工具:https://download.csdn.net/download/u011251940/11341326

致谢

以上是对Libmodbus TCP通讯的简单整理,学习过程离不开他人的帮助,感谢源博主分享
libmodbus TCP断开重连

int server_socket_init(){ int server_sockfd; struct sockaddr_in server_address; server_sockfd = socket(AF_INET, SOCK_STREAM, 0);//建立服务器端socket if(server_sockfd < 0 ) return -1; bzero(&server_address,sizeof(server_address)); server_address.sin_family = AF_INET; //server_address.sin_addr.s_addr = htonl(INADDR_ANY); //本机 server_address.sin_addr.s_addr = inet_addr(SERVER_IP); server_address.sin_port = htons(SERVER_PORT); if(bind(server_sockfd, (struct sockaddr *)&server_address,sizeof(server_address)) < 0 ) { close(server_sockfd); return -1; } if(listen(server_sockfd, 5) < 0) { close(server_sockfd); return -1; } return server_sockfd; } int server_Listening(int server_sockfd) { struct sockaddr_in client_address; int client_sockfd, ret = 0; int select_result,fd,client_len,data_size; struct timeval timeout; fd_set readfds, testfds; FD_ZERO(&readfds); FD_SET(server_sockfd, &readfds); while(1) { //每一轮监听后结构体被清0,每监听完一轮就要对结构体重新赋值,指定监听对象 testfds = readfds; timeout.tv_sec = 2; timeout.tv_usec = 500000; select_result = select(FD_SETSIZE, &testfds,NULL,NULL,NULL); if (select_result < 0) { return -1; } //perr_exit("select error"); for(fd = 0; fd < FD_SETSIZE; fd++) /*扫描所有的socket(文件)描述符*/ { if(FD_ISSET(fd,&testfds))/*找到可以读写相关socket(文件)描述符*/ { if(fd == server_sockfd) //为服务器socket,是则表示为客户请求连接。 { client_len = sizeof(client_address); client_sockfd = accept(server_sockfd,(struct sockaddr *)&client_address,&client_len); if(client_sockfd < 0) return -1; FD_SET(client_sockfd, &readfds);//将客户端socket加入到集合中 } else //客户端socket中有数据请求时 { ioctl(fd, FIONREAD, &data_size);//nread得到fd缓冲区的大小,就是当client写入缓冲区,这操作是读取缓冲区的大小 // n=read(fd,buf,sizeof(buf));//n即和nread一致 /*客户数据请求完毕,关闭套接字,从集合中清除相应描述符 */ if(data_size == 0) { //test FASTCGI_LOG("\n client_close_remore :%d\n\n\n\n",fd); close(fd); FD_CLR(fd, &readfds); } else if(!PerformServerTransfer(fd)){ return -1; } } } } } }这个是tcp server端有误么
07-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值