当客户端访问 服务器时候,服务器为每个用户分别开一个线程 并且创建Socket用于传递数据。当某个用户把数据传输给服务器时,服务器又要把接收到的数据转发给另一个用户,从接收的数据中可以知道要转发的用户的IP地址,请问转发应该怎么实现?谢谢!!

解决方案 »

  1.   

    其实不需要每个用户都一个线程,实际上只需要2个线程就可以实现多用户连接.定义一个Socket数组存放所有用户连接。服务器接受消息时可以知道客户的Socket序号,然后根据Socket调用Socket的API函数得到IP地址就可以,有了IP地址就可以再调用API函数找到对于的Socket,再发送消息就可以了。
      

  2.   

    谢谢上面的仁兄! 您说的:"有了IP地址就可以再调用API函数找到对于的Socket",这个功能实现的代码该怎么写?万分感谢!!!如果按照我的做法即:“当客户端访问 服务器时候,服务器为每个用户分别开一个线程”,知道IP,怎么可以知道它对应的与服务器建立连接的线程,实现代码应该怎么写,谢谢!!!!
      

  3.   

    建一个数组或链表来保存每个连接的信息结构
    typedef struct _ConnInfo
    {
      HANDLE hThread;
      SOCKET Socket;
      ULONG  IP;
    }*P_ConnInfo;
    这样知道IP后在可以在数组或链中查询对应的套接字或线程句柄,然后使用该套接发送数据.如果一定要转到相应的线程发送数据,可以在为每个连接建立的线程中设置一个消息循环,
    在查找到上述连接信息后向该线程发送消息.Buf已知;
    IP已知;
    P_ConnInfo pConnInfo=List.Find(IP);//这个可以使用STL的list类或MFC的CList类,或数组
    if(pConnInfo)
    PostThreadMessage(pConnInfo->hThread,自定议消息,0,(LONG)Buf);线程消息循环的建立:
    void ThreadProc(void* pVoid)
    {
      MSG msg;
      while(GetMessage(&msg,0,0,0))
      {
        switch(msg.lParam)//或if,看你的情况了.
        {
          消息判断及相应的处理;
        }
      } 
    }
      

  4.   

    #include <winsock2.h>
    #include <stdio.h>#define PORT    5150
    #define MSGSIZE 1024#pragma comment(lib, "ws2_32.lib")int      g_iTotalConn = 0;
    SOCKET   g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];
    WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];DWORD WINAPI WorkerThread(LPVOID);
    void Cleanup(int index);int main()
    {
      WSADATA     wsaData;
      SOCKET      sListen, sClient;
      SOCKADDR_IN local, client;
      DWORD       dwThreadId;
      int         iaddrSize = sizeof(SOCKADDR_IN);  // Initialize Windows Socket library
      WSAStartup(0x0202, &wsaData);  // Create listening socket
      sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_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);
        printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));    // Associate socket with network event
        g_CliSocketArr[g_iTotalConn] = sClient;
        g_CliEventArr[g_iTotalConn] = WSACreateEvent();
        WSAEventSelect(g_CliSocketArr[g_iTotalConn],
                       g_CliEventArr[g_iTotalConn],
                       FD_READ | FD_CLOSE);
        g_iTotalConn++;
      }
    }DWORD WINAPI WorkerThread(LPVOID lpParam)
    {
      int              ret, index;
      WSANETWORKEVENTS NetworkEvents;
      char             szMessage[MSGSIZE];  while (TRUE)
      {
        ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);
        if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
        {
          continue;
        }    index = ret - WSA_WAIT_EVENT_0;
        WSAEnumNetworkEvents(g_CliSocketArr[index], g_CliEventArr[index], &NetworkEvents);    if (NetworkEvents.lNetworkEvents & FD_READ)
        {
          // Receive message from client
          ret = recv(g_CliSocketArr[index], szMessage, MSGSIZE, 0);
          if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
          {
            Cleanup(index);
          }
          else
          {
            szMessage[ret] = '\0';
            send(g_CliSocketArr[index], szMessage, strlen(szMessage), 0);
          }
        }    if (NetworkEvents.lNetworkEvents & FD_CLOSE)
      {
       Cleanup(index);
      }
      }
      return 0;
    }void Cleanup(int index)
    {
      closesocket(g_CliSocketArr[index]);
     WSACloseEvent(g_CliEventArr[index]); if (index < g_iTotalConn - 1)
     {
      g_CliSocketArr[index] = g_CliSocketArr[g_iTotalConn - 1];
      g_CliEventArr[index] = g_CliEventArr[g_iTotalConn - 1];
     }
     
     g_iTotalConn--;
    }
    以上代码节选自书籍上的代码。你的问题只要略为修改就可以达到目的。至于由sock得到ip地址可以用int getpeername(SOCKET s, struct sockaddr FAR * name, int FAR * namelen )函数。遍历sock数组调用此函数,若得到的ip于你的转发ip相等,必定是此sock了,然后send就是.