首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SCTP:在连续的connect()调用之后,SCTP套接字的sctp_status.sstate值应该是多少?

SCTP:在连续的connect()调用之后,SCTP套接字的sctp_status.sstate值应该是多少?
EN

Stack Overflow用户
提问于 2017-04-26 04:25:26
回答 1查看 339关注 0票数 1

我试图通过SCTP连接到远程对等点(除了通过套接字和ping连接到它之外,我没有其他目录访问权限)。假设我已经成功地连接了,如果我尝试调用getsocktopt(),那么我的sctp_status.sstate的值应该是多少?根据sctp.h的说法,我的是SCTP_COOKIE_ECHOED(3)。这是正确的吗?不是应该是SCTP_ESTABLISHED吗?

因为我尝试用以下代码向远程对等程序发送消息:

代码语言:javascript
复制
ret = sctp_sendmsg (connSock, (void *) data, (size_t) strlen (data), (struct sockaddr *) &servaddr, sizeof (servaddr), 46, 0, 0, 0, 0);

它返回我尝试发送的字节数。然后当我试图捕捉到有任何反应时:

代码语言:javascript
复制
ret = sctp_recvmsg (connSock, (void *) reply, sizeof (reply), NULL,
          NULL, NULL, &flags);

它返回-1与errno的ECONNRESET(104)。在我的代码中,或者在我的流程中,有哪些可能的错误?我错过了什么吗?

提前谢谢你的回答。会很高兴的。:)

更新:下面是我连接到远程对等点的客户端代码。它实际上是我要使用的一个节点插件,因为在节点中不完全支持SCTP。使用lksctp工具包来包含标头。

代码语言:javascript
复制
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#include <signal.h>
#define MAX_BUFFER 1024

int connSock = 0;

int connect(char host[], int port, char remote_host[], int remote_port, int timeout) {

  int ret, flags;
  fd_set rset, wset;
  struct sockaddr_in servaddr;
  struct sockaddr_in locaddr;
  struct sctp_initmsg initmsg;
  struct timeval tval;
  struct sctp_status status;
  socklen_t opt_len;

  errno = 0;

  connSock = socket (AF_INET, SOCK_STREAM, IPPROTO_SCTP);
  flags = fcntl(connSock, F_GETFL, 0);
  fcntl(connSock, F_SETFL, flags | O_NONBLOCK);

  if (connSock == -1)
  {
      return (-1);
  }

  memset(&locaddr, 0, sizeof(locaddr));
  locaddr.sin_family = AF_INET;
  locaddr.sin_port = htons(port);
  locaddr.sin_addr.s_addr = inet_addr(host);

  ret = bind(connSock, (struct sockaddr *)&locaddr, sizeof(locaddr));

  if (ret == -1)
  {
      return (-1);
  }

  memset (&initmsg, 0, sizeof (initmsg));
  initmsg.sinit_num_ostreams = 5;
  initmsg.sinit_max_instreams = 5;
  initmsg.sinit_max_attempts = 10;
  ret = setsockopt(connSock, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg));

  if (ret == -1)
  {
      return (-1);
  }

  memset (&servaddr, 0, sizeof (servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons (remote_port);
  servaddr.sin_addr.s_addr = inet_addr (remote_host);

  if((ret = connect (connSock, (struct sockaddr *) &servaddr, sizeof (servaddr))) < 0)
      if (errno != EINPROGRESS)
          return (-1);

  if (ret == 0) {
      fcntl(connSock, F_SETFL, flags);
      return 0;
  }

  FD_ZERO(&rset);
  FD_SET(connSock, &rset);
  wset = rset;
  tval.tv_sec = timeout;
  tval.tv_usec = 0;

  ret = select(connSock+1, &rset, &wset, NULL, timeout ? &tval : NULL);

  if (ret == 0) {
      close(connSock);
      errno = ETIMEDOUT;
      return(-1);
  }
  else if (ret < 0) {
      return(-1);
  }

  fcntl(connSock, F_SETFL, flags);

  opt_len = (socklen_t) sizeof(struct sctp_status);
  getsockopt(connSock, IPPROTO_SCTP, SCTP_STATUS, &status, &opt_len);

  printf ("assoc id  = %d\n", status.sstat_assoc_id);
  printf ("state     = %d\n", status.sstat_state);
  printf ("instrms   = %d\n", status.sstat_instrms);
  printf ("outstrms  = %d\n", status.sstat_outstrms);

  return 0;
}

int sendMessage(char remote_host[], int remote_port, char data[]) {

  int ret, flags;
  struct sockaddr_in servaddr;
  char reply[1024];

  errno = 0;

  memset (&servaddr, 0, sizeof (servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons (remote_port);
  servaddr.sin_addr.s_addr = inet_addr (remote_host);

  printf("\nSending %s (%li bytes)", data, strlen(data));

  ret = sctp_sendmsg (connSock, (void *) data, (size_t) strlen (data),
          (struct sockaddr *) &servaddr, sizeof (servaddr), 46, 0, 0, 0, 0);

  if (ret == -1)
  {
    printf("\nError sending errno(%d)", errno);
    return -1;
  }
  else {
    ret = sctp_recvmsg (connSock, (void *) reply, sizeof (reply), NULL,
          NULL, NULL, &flags);

    if (ret == -1)
    {
      printf("\nError receiving errno(%d)", errno);
      return -1;
    }
    else {
      printf("\nServer replied with %s", reply);
      return 0;
    }
  }
}

int getSocket() {

  return connSock;
}

我不知道是否有什么重要的事情,我需要先设定,然后再连接,我错过了。我从不同的来源得到了片段,所以很混乱。

另一个更新,以下是执行时该代码的t鲨日志:

代码语言:javascript
复制
3336.919408  local  -> remote SCTP 82 INIT
3337.006690  remote -> local  SCTP 810 INIT_ACK
3337.006727  local  -> remote SCTP 774 COOKIE_ECHO
3337.085390  remote -> local  SCTP 50 COOKIE_ACK
3337.086650  local  -> remote SCTP 94 DATA
3337.087277  remote -> local  SCTP 58 ABORT
3337.165266  remote -> local  SCTP 50 ABORT

详细的这里日志。

看起来远程发送了它的COOKIE_ACK块,但是我的客户端未能将它的状态设置为已建立(我双倍地检查了sstate值3 这里)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-27 00:10:09

如果关联设置过程已完成,则状态应为SCTP_ESTABLISHED。SCTP_COOKIE_ECHOED指出,该协会尚未完全建立起来。这意味着起始端(在本例中是您的本地主机)发送了(一次或多次) COOKIE_ECHO块,该块尚未被COOKIE_ACK从远程端确认。

您可以在这种状态下发送消息(SCTP只需对其进行缓冲,直到获得COOKIE_ACK并在稍后重新发送)。

根据你提供的信息,很难说出了哪里出了问题。在这个阶段,可能值得深入研究wireshark跟踪,看看您的COOKIE_ECHO上有什么远程响应。

此外,如果您可以共享客户端/服务器端代码,这可能有助于确定根本原因。

更新1:还应该注意的是,应用程序可以自行中止关联(例如,如果该关联未在该服务器上配置)。如果您试图连接到随机服务器(而不是特定的服务器),这是非常可能的,而且在您的情况下确实是有意义的。在这种情况下,您的关联状态是COOKIE_ECHOED,因为COOKIE_ACK还没有到达(只是一个竞赛条件)。如前所述,SCTP愉快地接受处于这种状态的数据,并只是缓冲它直到它接收到COOKIE_ACK。远程端的SCTP会立即发送COOKIE_ACK,甚至在应用程序收到accept()中的执行控制之前也是如此。如果应用程序决定以不光彩的方式终止关联,它将发送中止(这是您在wireshark跟踪中的第一次中止)。您的一方尚未收到此中止,并发送数据块。因为远程端认为这个关联已经结束了,所以它不能处理数据块,所以它会意外地处理它(参见RFC 4960,第8.4章),并发送另一个t位设置为1的中止。只要查一下wireshark的痕迹,就可以很容易地确认它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43625026

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档