【问题标题】:MultiSocket Listening Linux Socket ProgramingMultiSocket 监听 Linux 套接字编程
【发布时间】:2014-02-10 22:58:49
【问题描述】:

这是我编写的简单代码。服务器响应端口 2923、2924 和 2925 上的 CONNECTIONS。

当我运行程序时,服务器只接受来自 2923 端口的连接。有人可以帮帮我吗?谢谢

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>

void handle_client(int cliend_fd)
{

  int ret = accept(cliend_fd, NULL, 0);
  if (ret < 0)
  {
    printf("Accept Error\n");
  }

  else
  {
    printf("Client Accepted\n");
    shutdown(ret, 2);
  }
}

int main()
{
  int count = 3;
  int PORT = 2923;

  struct sockaddr_in address;
  int MasterSocket[count];
  int i = 0;
  fd_set readfds;

  int maxfd;
  maxfd = -1;
  int SelectSession;

  struct timespec TimeOut;
  TimeOut.tv_sec = 2;
  TimeOut.tv_nsec = 2;

  for (i = 0; i < count; i++)
  {
    MasterSocket[i] = socket(AF_INET, SOCK_STREAM, 0);
  }

  for (i = 0; i < count; i++)
  {
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr("127.0.0.1");
    address.sin_port = PORT + i;
    if (bind(MasterSocket[i], (struct sockaddr *) &address, sizeof(address))
        < 0)
    {
      perror("Bind\n");
      getchar();
    }

    printf("SockerDesriptor %d---bind %d\n", MasterSocket[i], PORT + i);
  }

  for (i = 0; i < count; i++)
  {
    if (listen(MasterSocket[i], 4) < 0)
    {
      perror("Listen");
      getchar();
      //return 1;
    }
    else
    {
      printf("Listening on Port %d---\n", PORT + i);
    }
  }

  while (1)
  {
    FD_ZERO(&readfds);
    int status;

    for (i = 0; i < count; i++)
    {
      FD_SET(MasterSocket[i], &readfds);
      if (MasterSocket[i] > maxfd)
      {
        maxfd = MasterSocket[i];
      }
      printf("%d Added to FD_SET Descriptor %d \n\n", PORT + i,
          MasterSocket[i]);
    }

    //status = 0;
    printf("############Waiting for Connection\n");
    status = pselect(maxfd + 1, &readfds, NULL, NULL, &TimeOut, NULL );
    if (status < 0)
    {
      perror("Status");
      getchar();
      return 1;
    }

    else if (status == 0)
    {
      printf("TimeOut occured\n");
    }

    else
    {
      //printf("Status %d\n", status);
      SelectSession = -1;
      for (i = 0; i < count; i++)
      {
        //printf("Checking Set %d\n", i);
        if (FD_ISSET(MasterSocket[i], &readfds))
        {
          //printf("Matching Set %d\n", i);
          SelectSession = MasterSocket[i];
          printf("SelectSession %d\n", MasterSocket[i]);
          if (SelectSession == -1)
          {
            //shutdown (MasterSocket[i], 2);
            //continue;
            break;
          }
          else
          {
            printf("In Handle\n");
            handle_client(SelectSession);
            getchar();
          }

        }
        else
        {
          printf("Not in FD_ISSET\n");

        }
      }
    }

    /*for (i=0; i<count; i++)
     {
     shutdown (MasterSocket[i], 2);
     }
     */
  }

  return 0;
}

【问题讨论】:

  • 在程序执行过程中,bind()listen()pselect() 和/或accept() 是否有任何错误?
  • 代码编译时没有警告吗?
  • 这里的代码在完成#define _POSIX_C_SOURCE 200112L 后编译干净,以提取pselect() 的原型并按预期工作。
  • 你用什么连接服务器?
  • 使用了客户端程序。连接端口。仅接受 2923

标签: c linux sockets networking port


【解决方案1】:

从 while 循环中删除 getchar()

pselect 服务器等待获取字符之后,因此不再允许连接客户端。

或者你必须在每个客户端连接后在服务器中输入一个字符

并使用htons将端口号更改为网络字节顺序

程序:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>

void handle_client (int cliend_fd)
{
    int ret = accept(cliend_fd, NULL, 0);
    if ( ret < 0 )
        printf("Accept Error\n");
    else {
        printf ("Client Accepted\n");
        shutdown (ret, 2);
    }
    return;
}

int main()
{
    int count = 3, PORT = 8000, opt = 1, i = 0;
    int MasterSocket[count];
    int maxfd = -1, SelectSession;
    fd_set readfds;
    struct sockaddr_in address;

    struct timespec TimeOut;
    TimeOut.tv_sec = 2;
        TimeOut.tv_nsec = 2;

    for(i=0; i<count; i++)
    {
        MasterSocket[i] = socket(AF_INET , SOCK_STREAM , 0);
        printf("socket created : %d\n", MasterSocket[i]);
    }

    for(i=0; i<count; i++)
    {
        address.sin_family = AF_INET;
        address.sin_addr.s_addr = inet_addr("192.168.1.4");
        address.sin_port = htons(PORT+i);
        if( setsockopt(MasterSocket[i], SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 ) {    
            perror("setsockopt1");
            return -1;
        }
        if (bind(MasterSocket[i], (struct sockaddr *)&address, sizeof(address)) < 0) {
            perror ("Bind\n");
            return -1;
        }
        printf("SockerDesriptor %d---bind %d\n", MasterSocket[i], PORT+i);
    }

    for(i=0; i<count;i++)
    {
        if (listen(MasterSocket[i], 4) < 0) {
                perror ("Listen\n");
                return -1;
        }
        else
            printf("Listening on Port %d---\n", PORT+i);    
    }

    while(1)
    {   
        FD_ZERO(&readfds);
        int status;
        for (i = 0; i < count; i++)
        {
            FD_SET(MasterSocket[i], &readfds);
            if (MasterSocket[i] > maxfd)
                maxfd = MasterSocket[i];
        }

        status = pselect(maxfd + 1, &readfds, NULL, NULL, &TimeOut, NULL );
        if(status < 0)
            perror("Status");
        /* else if(status == 0)
            printf("TimeOut occured\n"); */
        else if(status > 0) {
            for (i = 0; i < count; i++)
            {
                if (FD_ISSET(MasterSocket[i], &readfds)) {
                    SelectSession = MasterSocket[i];
                    printf("SelectSession %d\n", MasterSocket[i]);
                    handle_client(SelectSession);
                    //getchar();
                }
            }
        }
    }
    return 0;
}       

【讨论】:

  • 工作中...感谢您的帮助 \m/。是的,我查了SO_REUSEADDRgetchar()。我忽略了一个小细节。我用count +1 调用了“pselect”而不是maxfd+1
【解决方案2】:

这一行

 address.sin_port = PORT + i;

应该是

 address.sin_port = htons(PORT + i);

确保端口按网络字节顺序存储。


另外你应该close()一个套接字描述符在关闭它之后,如果你不再需要它,释放与之相关的系统资源。

【讨论】:

    猜你喜欢
    • 2011-11-14
    • 2012-09-26
    • 2011-02-15
    • 1970-01-01
    • 2013-03-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2016-04-06
    相关资源
    最近更新 更多