SDK之SOCKET服务端

来源:互联网 发布:linux命令行修改ip 编辑:程序博客网 时间:2024/05/21 11:24


#include<winsock2.h>
#include<ws2tcpip.h>
#include<stdio.h>
#pragma comment(lib, "ws2_32.lib")

/*常量*/
#define DEFAULT_PORT "1000"  //端口
#define MAX_REQUEST 1024  //接收数据的缓存
#define BUF_SIZE 4096     //发送数据缓存
/************************
* CommuncationThread
* 功能:用于接收和发送数据的线程
*       为每个连接客户端创建一个数据发送的线程
*       可以使用多个客户端同时连接到服务端
* 参数:lpParameter、SOCKET
*************************/
DWORD WINAPI CommunicationThread(
         LPVOID lpParameter
         )
{
 DWORD dwTid = GetCurrentThreadId();
 //获得参数
 SOCKET socket = (SOCKET) lpParameter;
 //接收数据分配空间
 LPSTR szRequest = (char *)HeapAlloc(
  GetProcessHeap(),
  0 ,
  MAX_REQUEST);
 int iResult;
 int bytesSent; //用于保存send的返回值,即实际发送的数据的大小

 //接收数据
 iResult = recv(socket,//socket
  szRequest,    //接收缓存
  MAX_REQUEST, //缓存大小
  0);           //无标志
 if(iResult == 0)  //接收数据失败,连接关闭
 {
  printf("Connection closing....\n");
  HeapFree(GetProcessHeap(), 0 , szRequest);
  closesocket(socket);
  return 1;
 }
  else if(iResult == SOCKET_ERROR) //接收数据失败,Socket错误
  {
   printf("recv faild:%d\n",WSAGetLastError());
   HeapFree(GetProcessHeap(), 0 , szRequest);
   closesocket(socket);
  return 1;

  }
  else if(iResult > 0)  //接收数据成功
  {
   //显示接收到的数据
   printf("\tCommunicationThread(%d)\tBytes received:%d\n",dwTid,iResult);
   printf("\tCommunicationThread(%d)\trequest string is:%s\n",dwTid,szRequest);

   //如果接收到的数据是“download file”
   if(lstrcmpi(szRequest,"download file") == 0)
   {
    //读取文件 download.txt 将发送
    HANDLE hFile;
    LPVOID lpReadBuf;  //发送缓存
    DWORD dwBytesRead;
    DWORD dwFileSize;
    DWORD dwSendFile = 0;
    hFile = CreateFile("download.txt",
     GENERIC_READ,
     FILE_SHARE_READ,
     NULL,
     OPEN_EXISTING,
     FILE_ATTRIBUTE_NORMAL,
     NULL);
    if(hFile == INVALID_HANDLE_VALUE)
    {
     printf("\tCommunicationThread\tCould not open file(error %d)\n",
      GetLastError());
     send(socket,"error",6,0);
     closesocket(socket);
     return 1;
    }
             //分配发送数据的缓存
    lpReadBuf = HeapAlloc(GetProcessHeap(), 0 , BUF_SIZE);
    //获得文件大小
    dwFileSize = GetFileSize(hFile,NULL);
    //循环发送
    while(1)
    {
     //读文件到缓存
     if(!ReadFile(hFile, lpReadBuf , BUF_SIZE ,&dwBytesRead,NULL))
     {
      printf("\tCommunicationThread\t Could not read file(error %d)\n",GetLastError());
      closesocket(socket);
      CloseHandle(hFile);
      return 1;
     }
     //发送读取的文件数据
     bytesSent = send(socket,
      (const char*)lpReadBuf,
      dwBytesRead,
      0);
     if(bytesSent == SOCKET_ERROR)
     {
      printf("\tCommunicationThread\tsend error %d\n",
       GetLastError());
      closesocket(socket);
      CloseHandle(hFile);
      return 1;
     }
     //显示发送数据的大小
      printf("\tCommunicationThread(%d)\tsend %d Bytes\n",dwTid,bytesSent);
      //累加已发送的大小
      dwSendFile  = dwSendFile +dwBytesRead;
      //如果所有数据已发送
      if(dwSendFile == dwFileSize)
      {
        printf("\tCommunicationThread\tFile download ok\n");
        break;//退出循环
      }
   }
    //释放内存、关闭连接、关闭文件
    HeapFree(GetProcessHeap(), 0 , lpReadBuf);
    CloseHandle(hFile);
    closesocket(socket);
  }
  //如果接收到的数据是 “get information”
   else if(lstrcmpi(szRequest, "get information") == 0)
   {
    //发送数据
    bytesSent = send(socket, //socket
     "this is information",//数据
     lstrlen("this is information") + 1,//数据长度
     0); //标志
    //判断是否成功
    if(bytesSent == SOCKET_ERROR)
    {
     printf("\tCommunicationThread\tsend error %d\n",WSAGetLastError());
     closesocket(socket);
     return 1;
    }
    printf("\tCommunicationThread(%d)\tsend %d Bytes\n",dwTid,bytesSent);
   }
   else //收到未知数据
   {
    printf("unreferenced request\n");
   }
  }
  //释放接收数据缓存,关闭Socket
  HeapFree(GetProcessHeap(), 0 ,szRequest);
  closesocket(socket);
  return 0;
  }
 
/*********************
* int _cdecl main(void)
* 功能 Socket服务端程序
**********************/
int _cdecl main(void)
{
 WSADATA wsaData;
 SOCKET ListenSocket = INVALID_SOCKET;  //监听Socket
 SOCKET ClientSocket = INVALID_SOCKET;  //连接Scoket
 struct addrinfo *result = NULL,hints;
 int iResult;    //保存返回结果
 
 //初始化WinSocke,保证Ws_32.dll已经加载
 iResult = WSAStartup(MAKEWORD(2,2),&wsaData);
 if(iResult !=0 )
 {
  printf("WSAStartup failed: %d\n",iResult);
  return 1;
 }
 //地址
 ZeroMemory(&hints, sizeof(hints));
 hints.ai_family = AF_INET;
 hints.ai_socktype = SOCK_STREAM;
 hints.ai_protocol = IPPROTO_TCP;
 hints.ai_flags = AI_PASSIVE;

 //获取主机地址,保证网络协议可用
 iResult = getaddrinfo(NULL, //本机
  DEFAULT_PORT,   //端口
  &hints,                 //使用的网络协议、连接类型
  &result);               //结果
 if(iResult !=0 )
 {
  printf("getaddrinfo failed: %d\n",iResult);
  WSACleanup();
  return 1;
 }
//创建Socket,用于监听
 ListenSocket = socket(result->ai_family , //网络协议、AF_INEF,Ipv4
  result->ai_socktype ,                 //类型,SOCK_STREAM
  result->ai_protocol );                //通信协议,TCP
 if(ListenSocket == INVALID_SOCKET)
 {
  printf("socket failed: %ld\n",WSAGetLastError());
  freeaddrinfo(result);
  return 1;
 }
 //绑定到端口
 iResult = bind(ListenSocket,result->ai_addr ,(int)result->ai_addrlen );
 if(iResult == SOCKET_ERROR)
 {
  printf("bind failed: %d\n",WSAGetLastError());
  freeaddrinfo(result);
  WSACleanup();
  return 1;
 }
 printf("bind\n");
 freeaddrinfo(result);  //result 不再使用

 //开始监听
 iResult = listen(ListenSocket,SOMAXCONN);
 printf("start listen......\n");
 if(iResult == SOCKET_ERROR)
 {
  printf("bind failed: %d\n",WSAGetLastError());
  freeaddrinfo(result);
  WSACleanup();
  return 1;
 }
 while(1)
 {
  //接收客户端的连接,accept函数会等待,直到连接建立
  printf("ready to accept \n");
  ClientSocket =accept(ListenSocket,NULL,NULL);
  //accept 函数返回,说明已经有客户端连接
  //返回连接Socket
  printf("accept a connection\n");
   if(ClientSocket == INVALID_SOCKET)
   {
    printf("accept failed: %d\n",WSAGetLastError());
    closesocket(ListenSocket);
    break; //等待连接错误,退出循环
   }
   //为每一个连接创建一个数据发送的接收线程
   //使服务端又可以立即接收其他客户的连接
   if(!CreateThread(NULL,
    0,
    CommunicationThread,//线程函数
    (LPVOID)ClientSocket,//将Socket作为参数
    0,
    NULL))
   {
    printf("Create Thread error (%d)",GetLastError());
    break;
   }
 }
 //循环退出,释放DLL
 WSACleanup();
 return 0;
}

 

原创粉丝点击