如何使用C语言创建一个TCP套接字连接到预定端口

11

我有一个非常简单的问题。我想测试特定端口当前是否正在使用中。为此,我想将TCP套接字绑定到该端口,如果连接被拒绝,则表示该端口正在使用中,否则表示端口空闲。

请问有人可以告诉我如何在C语言中编写TCP套接字代码吗?我在Solaris平台上。

我知道这很基础。但是我感谢您的帮助。提前致谢。

4个回答

12

如果出现错误,包括地址已经被使用的情况,调用bind函数将返回-1。

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 12345

int main()
{
  struct sockaddr_in addr;
  int fd;

  fd = socket(AF_INET, SOCK_STREAM, 0);
  if(fd == -1)
  {
      printf("Error opening socket\n");
      return -1;
  }

  addr.sin_port = htons(PORT);
  addr.sin_addr.s_addr = 0;
  addr.sin_addr.s_addr = INADDR_ANY;
  addr.sin_family = AF_INET;

  if(bind(fd, (struct sockaddr *)&addr,sizeof(struct sockaddr_in) ) == -1)
  {
      printf("Error binding socket\n");
      return -1;
  }

  printf("Successfully bound to port %u\n", PORT);
}

8

这取决于您要测试的内容。

按照joelc的建议使用bind()会告诉您端口是否在计算机上的任何接口上打开。虽然为了彻底,您不仅应该检查bind()的返回值,还应该检查errno == EADDRINUSE

即(修改joelc的代码)


if(bind(socket, (struct sockaddr *)&sin,sizeof(struct sockaddr_in) ) == -1)
{
    if( errno == EADDRINUSE )
    {
        // handle port already open case
    }
    else
    {
        // handle other errors
    }
}

通过更改以下行中使用的地址,例如:


    sin.sin_addr.s_addr = inet_addr("192.168.1.1");

你可以测试特定接口上的端口是否可用。

但要注意,这并不是端口状态的完美测试。如果另一个进程打开了该端口,并在正常关闭端口之前终止了(即在套接字上调用close()之前),那么通常会收到相同的EADDRINUSE错误。(这取决于是否在套接字上设置了SO_REUSEADDR选项)

(顺便说一句:除非您的测试应用程序具有足够的特权,否则无法绑定到1024以下的任何端口)

正如Anonymous所建议的那样,您还可以查看netstat。这将为您提供所有可以通过重复调用bind()获得的相同信息,但速度更快且没有任何副作用(例如它不必实际绑定到端口,这会使它们对任何其他进程都不可用)。 只需调用netstat -a --numeric-ports -t并分析输出,就可以获得您想要的所有内容。

关于moogs的建议,调用telnet每个端口只会告诉您该端口上是否有一个套接字在侦听 - 而不是它是否真的开放。


-1

你只是想测试特定的端口是否正在被使用吗?(并不需要编写程序)。 如果是这样,你可以使用telnet:

telnet 主机名 端口号

如果连接失败,则该端口当前未被使用。如果连接成功并等待你的输入,则说明该端口正在被使用 :)


1
这只会告诉你该端口是否存在监听套接字,而不是它是否打开。 - Andrew Edgecombe

-2
你可能想要查看 netstat 的源代码。我相信 Solaris 也有一个 netstat。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接