为了账号安全,请及时绑定邮箱和手机立即绑定

请问在网络编程中select函数如何接受一个accept事件?

请问在网络编程中select函数如何接受一个accept事件?

蝴蝶不菲 2019-07-09 10:06:52
网络编程中select函数如何接受一个accept事件
查看完整描述

3 回答

?
冉冉说

TA贡献1877条经验 获得超1个赞

#include <winsock.h>

#include <stdio.h>

#define PORT       5150 //端口

#define MSGSIZE    1024 //信息大小

#pragma comment(lib, "ws2_32.lib")

int    g_iTotalConn = 0; //连接数量

SOCKET g_CliSocketArr[FD_SETSIZE]; //套接字数组

DWORD WINAPI WorkerThread(LPVOID lpParameter);//线程函数

int main()

{

  WSADATA     wsaData;

  SOCKET      sListen, sClient;

  SOCKADDR_IN local, client;

  int         iaddrSize = sizeof(SOCKADDR_IN);

  DWORD       dwThreadId;

  // Initialize Windows socket library

  //装载套接字库

  WSAStartup(0x0202, &wsaData);

  // Create listening socket

  //创建套接字

  sListen = socket(AF_INETSOCK_STREAMIPPROTO_TCP);

  // Bind

  //绑定

  local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

  local.sin_family = AF_INET;

  local.sin_port = htons(PORT);

  bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));

  // Listen

  //监听

  listen(sListen, 3);

  // Create worker thread

  //创建线程

  CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId); 

 

  while (TRUE)

  {

    // Accept a connection

    //接受一个连接,返回的是客户套的套接字

    sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);

    //这里client的SOCKADDR_IN  client 中可以取出IP

    printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));

    // Add socket to g_CliSocketArr

    //把客户端套接字放入数组中

    g_CliSocketArr[g_iTotalConn++] = sClient;

  }

  

  return 0;

}


DWORD WINAPI WorkerThread(LPVOID lpParam)//线程

{

  int            i;

  fd_set         fdread;//结构

  int            ret;

  struct timeval tv = {1, 0};//超时时间 SELECT模型中用到的这里是1秒

  char           szMessage[MSGSIZE];//信息数组,事实上就是个缓冲区

  

  while (TRUE)

  {

   

    FD_ZERO(&fdread);//清空fd_set结构

    for (i = 0; i < g_iTotalConn; i++)

    {

      FD_SET(g_CliSocketArr[i], &fdread);//把客户套接字放到SELECT要求的数组中

    }

    //**************************************

    // We only care read event

    //只关心读的情况

    ret = select(0, &fdread, NULL, NULL, &tv);

    if (ret == 0)

    {

      // Time expired 超时

      continue;

    }

    //如果SELECT返回不是0

    for (i = 0; i < g_iTotalConn; i++)

    {

      if (FD_ISSET(g_CliSocketArr[i], &fdread))

      {

        // A read event happened on g_CliSocketArr[i]

        //一个可读发生在这个套接字上

        ret = recv(g_CliSocketArr[i], szMessage, MSGSIZE, 0);

        //把它读出到缓冲区

      if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))

      {

      // Client socket closed

      //客户端关闭

          printf("Client socket %d closed.\n", g_CliSocketArr[i]);

         closesocket(g_CliSocketArr[i]);//关闭这个套接字

     

        if (i < g_iTotalConn - 1)

            { 

              //将数组中最后一个套接字挪到当前的位置上           

              g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];

            }

        }

      else

       {

       // We received a message from client

       //如果以上没发生,那么就接收到一个客户端的信息

          szMessage[ret] = '\0';

        //直接回送回去

          send(g_CliSocketArr[i], szMessage, strlen(szMessage), 0);

         }

       }

     }

  }

  

  return 0;

}

1



查看完整回答
反对 回复 2019-07-14
?
翻翻过去那场雪

TA贡献2065条经验 获得超13个赞

这样理解:
socket()的返回值是服务器本地监听用的fd,通过这个fd,可以判断是否有客户端连接上来,那些客户端连接上来,但是不能用这个fd用来和客户端通信。
listenfd是指客户端连接本机时的fd,是用来和客户端通信用的。

查看完整回答
反对 回复 2019-07-14
?
DIEA

TA贡献1820条经验 获得超2个赞

怎么在VS2005里面调试socket函数
一个VS2005 无法调试C++的问题
现象:在vs2005 中,建立一个空项目,添加一个c++文件main.cpp
#include iostream
using namespace std;int main(){cout hello ;}此时按f5 启动调试,即会提示项目无法调试:无法找到“xxx.exe”的调试信息,或者调试
信息不匹配。未使用调试信息生成二进制文件
搜了一些资料,都说建立项目的时候不应建立空项目,而应当建立一个console application。
人写到。 其实问题在于,在空项目中不生成调试文件pdb,所以无法调试。
要让项目生成pdb 文件,需要更改:
项目属性,configuration properties- linker- Generate Debug Info 从 no 改为 yes
但这样还是不够的,还需要更改:

查看完整回答
反对 回复 2019-07-14
  • 3 回答
  • 0 关注
  • 1244 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信