/************SERVER**************/
#include <winsock2.h>
#include <stdio.h>
#define PORT_A  11111
#define PORT_B  22222
void main(int argc, char **argv)
{
  WSADATA wsaData; // 套接口信息数据
  SOCKET socka; // 套接口a
  SOCKET sockb; // 套接口b
  
  int nPortA = PORT_A;
  int nPortB = PORT_B;
  fd_set rfd;   // 读描述符集
  timeval timeout;  // 定时变量
  sockaddr_in addr; // 告诉sock 应该在什么地方licence
  char recv_buf[1024];  // 接收缓冲区
  
  int nRecLen; // 客户端地址长度!!!!!!
  
  sockaddr_in cli;  // 客户端地址
  int nRet; // select返回值
  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
  {
    printf("failed to laod winsock!/n");
    return;
  }
  socka = socket(AF_INET, SOCK_DGRAM, 0); // 创建数据报socka
  if (socka == INVALID_SOCKET)
  {
    printf("socket()/n");
    return;
  }
  sockb = socket(AF_INET, SOCK_DGRAM, 0); // 创建数据报sockb
  if (sockb == INVALID_SOCKET)
  {
    printf("socket()/n");
    return;
  }
  memset(&addr, 0, sizeof(addr));
  
  addr.sin_family = AF_INET;   // IP协议
  addr.sin_port = htons(nPortA); // 端口
  addr.sin_addr.s_addr = htonl(INADDR_ANY); // 在本机的所有ip上开始监听
  if (bind(socka, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)// bind socka
  {
    printf("bind()/n");
    return;
  }
  
  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;   // IP协议
  addr.sin_port = htons(nPortB); // 端口
  addr.sin_addr.s_addr = htonl(INADDR_ANY); // 在本机的所有ip上开始监听
  
  if (bind(sockb, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) // bind sockb
  {
    printf("bind()/n");
    return;
  }
  // 设置超时时间为6s
  timeout.tv_sec = 6; 
  timeout.tv_usec = 0;
  
  memset(recv_buf, 0, sizeof(recv_buf)); // 清空接收缓冲区
  while (true)
  {
    FD_ZERO(&rfd); // 在使用之前总是要清空
    
    // 开始使用select
    FD_SET(socka, &rfd); // 把socka放入要测试的描述符集中
    FD_SET(sockb, &rfd); // 把sockb放入要测试的描述符集中
    
    nRet = select(0, &rfd, NULL, NULL, &timeout);// 检测是否有套接口是否可读
    if (nRet == SOCKET_ERROR) 
    {
      printf("select()/n");
      return;
    }
    else if (nRet == 0) // 超时
    {
      printf("timeout/n");
      closesocket(socka);
      closesocket(sockb);
      break;
    }
    else  // 检测到有套接口可读
    {
      if (FD_ISSET(socka, &rfd))  // socka可读
      {
        nRecLen = sizeof(cli);
        int nRecEcho = recvfrom(socka, recv_buf, sizeof(recv_buf), 0, (sockaddr*)&cli, &nRecLen);
        if (nRecEcho == INVALID_SOCKET)
        {
          printf("recvfrom()/n");
          break;
        }
        printf("data to port 11111: %s/n", recv_buf);
      }
      if (FD_ISSET(sockb, &rfd)) // sockb 可读
      {
        nRecLen = sizeof(cli);
        int nRecEcho = recvfrom(sockb, recv_buf, sizeof(recv_buf), 0, (sockaddr*)&cli, &nRecLen);
        if (nRecEcho == INVALID_SOCKET)
        {
          printf("recvfrom()/n");
          break;
        }
        printf("data to port 22222: %s/n", recv_buf);
      }
    }
  }
  WSACleanup();
}
/************CLIENT*************/
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#define SERVER_PORT_A 11111   // 服务器端口A
#define SERVER_PORT_B 22222   // 服务器端口B
typedef struct tagSERVER  // 服务器
{
  char* ip; // ip地址
  int nPort;  // 端口号
} SERVER, *PSERVER; 
int SendData(SOCKET s, char *ip, int nPort, char *pData); // 发送数据到IP:nPort
int main(int argc, char **argv)
{
  int i;
  WSADATA wsaData;    // socket数据
  SOCKET sClient;     // 客户端套接口
  char send_buf[] = "hello! I am LiangFei whoes SNO=06060734";  // 发送的数据内容
  int nSend; // 发送数据后的返回值
  // 服务器
  SERVER sers[] = { {"127.0.0.1", SERVER_PORT_A}, 
            {"127.0.0.1", SERVER_PORT_B} };
  int nSerCount = sizeof(sers) / sizeof(sers[0]); // 服务器个数
  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) // 启动socket
  {
    printf("failed to start up socket!/n");
    return 0;
  }
  
  // 建立客户端数据包套接口
  sClient = socket(AF_INET, SOCK_DGRAM, 0);
  if (sClient == INVALID_SOCKET)
  {
    printf("socket()/n");
    return 0;
  }
  for (i = 0; i < nSerCount; i++)
  {
    nSend = SendData(sClient, sers[i].ip, sers[i].nPort, send_buf);  // 发送数据
    if (nSend == 0)  // 发送失败
    {
      return 0;
    }
    else if (nSend == SOCKET_ERROR)  // 套接口出错
    {
      printf("sendto()/n");
      return 0;
    }
  }
  closesocket(sClient);  // 关闭套接口
  WSACleanup(); // 卸载winsock
  return 0;
}
int SendData(SOCKET s, char *ip, int nPort, char *pData)
{
  sockaddr_in ser;  // 服务器端地址  
  ser.sin_family = AF_INET;  // IP协议
  ser.sin_port = htons(nPort);  // 端口号
  ser.sin_addr.s_addr = inet_addr(ip);  // IP地址
  int nLen = sizeof(ser);  // 服务器地址长度
  
  return sendto(s, pData, strlen(pData) + 1, 0, (sockaddr*)&ser, nLen);  // 向服务器发送数据