Linux:select判断一个远程服务器的端口是否开放

思路:
socket创建套接字之后->connect连接;

但是存在一个问题,connect之后如果端口是不通的,那么阻塞默认是会过 几十秒才会重新connect。
所以这时候我们要设置connect为非阻塞。

非阻塞的情况下:connect不管怎么样立即返回-1,所以不能当作判断的依据。所以要通过select判断是否可对这个服务器写消息,来判断是否该服务器的端口开放。

代码如下:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>

using namespace std;

int main()
{
	int sockClient = socket(AF_INET, SOCK_STREAM, 0);
	struct sockaddr_in addrSrv;
	addrSrv.sin_addr.s_addr = inet_addr("47.107.53.238");
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(22);
	struct timeval tv = { 1,0 };//2s 超时
	setsockopt(sockClient, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval));

	int flag = fcntl(sockClient,3, 0);
	flag |= 04000;
	fcntl(sockClient, 4, flag);
	int ret = 0;
	while (1)
	{
		 ret = connect(sockClient, (const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));
		printf("connect ret:%d\n", ret);
		fd_set rfd, wfd;
		FD_ZERO(&wfd);
		FD_SET(sockClient, &wfd);
		ret = select(sockClient + 1, &rfd, &wfd, NULL, &tv);//注意必须是套接字最大值+1
		printf("now ret:%d\n", ret);

		if (FD_ISSET(sockClient, &wfd))
		{
			printf("open!\n");
			break;
		}
		else
		{
			printf("connect failed...\n");
		}
		sleep(1);
	}
	//又重新设置成阻塞
	flag = fcntl(sockClient, 3, 0);
	flag &= ~04000;
	fcntl(sockClient, 4, flag);

	//可以发送数据测试一下,如果单纯为了测试是否连通,直接关闭套接字就行了
	/*char buf[10] = { 0 };
	for (unsigned int i = 0; i < 5; i++)
	{
		buf[i] = 'd';
	}
	ret = send(sockClient, buf, sizeof(buf), 0);
	cout << "ret:" << ret <<"send success!"<< endl;
*/
	close(sockClient);

	return 0;
}

Guess you like

Origin blog.csdn.net/qq_40861091/article/details/88881877