lwip 基于select方式实现的tcp简易服务器

2023-05-16


#include "sock_api/sock_api.h"


void tcp_cli_task(void *arg)
{
    int     ret;
    int sock = arg;
    fd_set  readfds;
	fd_set  errofds;
	struct timeval timeo;
	while(1){
		FD_ZERO(&readfds);
		FD_SET(sock, &readfds);
		FD_ZERO(&errofds);
		FD_SET(sock, &errofds);

		timeo.tv_sec = 1;
		timeo.tv_usec = 1000 * 10;
        ret = select(sock + 1, &readfds, (fd_set *)0, &errofds, &timeo );
		if (ret == 0){//返回值等于0表示超时
            continue;
		}
		else if (ret < 0){//返回值小于于0表示出错

			printf("\n >>>>>> ret = %d\n",ret);
			break;
		}

		if (FD_ISSET(sock, &errofds))
		{
			printf("\n >>>>>> exit ok!\n");
			break;
		}


		if (FD_ISSET(sock, &readfds))
		{
            char buf[128];
            ret = recv(sock,buf,sizeof(buf),0);
            if(ret <= 0){
               printf("\n >>>>>> exit ok!\n");
                break;
            }
            put_buf(buf,ret);
		}
	}

}

void tcp_server_test(void *arg)
{
	struct sockaddr_in sin;  /* bind socket address */
	socklen_t   sinlen;     /* length of address */

	fd_set  readfds;
	fd_set  errofds;
	int     ret, sock;
	struct timeval timeo;
	int fd;
	struct sockaddr_in addr;
	int reuse;

	//申请一个套接字
	fd = socket(AF_INET, SOCK_STREAM, 0);
	if (fd < 0){
		printf("\n >>>>>> socket error\n");
        return;
	}
	//设置地址复用
	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse, sizeof(int)) < 0)
	{
		printf("\n >>>>>> setsockopt SO_REUSEADDR error\n");
        return;
	}

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr("192.168.1.106");
	addr.sin_port = htons(5200);
	//绑定ip和端口
	if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
	{
		close(fd);
		printf("\n >>>>>> bind error\n");
        return;
	}

    //获取当前描述符的flag
    int opts;
    opts=fcntl(fd, F_GETFL, 0);
    if(opts<0)
    {
		printf("\n >>>>>> F_GETFL error\n");
		return;
    }
	//设置当前描述符为非阻塞方式
    opts = opts | O_NONBLOCK;
    if(fcntl(fd,F_SETFL,opts)<0)
    {
		printf("\n >>>>>> F_SETFL error\n");
		return;
    }
	//设置监听
	if (listen(fd, 100) < 0)
	{
		close(fd);
		printf("\n >>>>>> listen error\n");
		return;
	}

	while (1)
	{
/*
FD_ZERO(fd_set *fdset);              // 将set清零使集合中不含任何fd
FD_SET(int fd, fd_set *fdset);       // 将fd加入set集合
FD_CLR(int fd, fd_set *fdset);       // 将fd从set集合中清除
FD_ISSET(int fd, fd_set *fdset);     // 检测fd是否在set集合中,不在则返回0
调用FD_ZERO将一个 fd_set 变量的所有位设置为0。要开启描述符集中的一位,可以调用FD_SET。调用FD_CLR可以清除一位。最后,可以调用FD_ISSET测试描述符集中的一个指定位是否已打开。
*/	
		FD_ZERO(&readfds);
		FD_SET(fd, &readfds);
		FD_ZERO(&errofds);
		FD_SET(fd, &errofds);
		timeo.tv_sec = 1;
		timeo.tv_usec = 1000 * 10;//设置超时时间
		ret = select(fd + 1, &readfds, (fd_set *)0, &errofds, &timeo );
		if (ret == 0){//返回值等于0表示超时
            continue;
		}
		else if (ret < 0){//返回值小于于0表示出错
			printf("\n >>>>>> ret = %d\n",ret);
			break;
		}
		if (FD_ISSET(fd, &errofds))
		{
			printf("\n >>>>>> exit ok!\n");
			break;
		}
		sinlen = sizeof(sin);
		if (FD_ISSET(fd, &readfds))
		{
			printf("\n >>>>>>  read ok!\n");
			sock = accept(fd, (struct sockaddr *)&sin, &sinlen);
            if(sock < 0){
                break;
            }
            thread_fork("tcp_cli_task",18,0x2000,64,0,tcp_cli_task,(void *)sock);
		}
	}
}

int sock_test(void)
{
    thread_fork("tcp_server_test", 18, 0x2E00, 64, 0, tcp_server_test, NULL);
	return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

lwip 基于select方式实现的tcp简易服务器 的相关文章

随机推荐