⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 service.c

📁 C语言源码
💻 C
字号:
/*导入库文件*/
#pragma comment(lib,"wsock32.lib")
/*加载头文件*/
#include <stdio.h>
#include <winsock2.h>
/*自定义函数原型*/
void initial();
int InitSockets(void);

void GetArgments(int argc, char **argv);
void ErrorPrint(x);
void userHelp();

int LoopControl(SOCKET listenfd, int isMultiTasking);

void Service(LPVOID lpv);

/*定义常量*/
#define MAX_SER 10
/*定义全局变量*/
char *hostName;
unsigned short maxService;
unsigned short  port;

/*初始化全局变量函数*/
void initial()
{
    hostName = "127.0.0.1";
    maxService = 3;
    port = 9999;
}

/*初始化Winsocket函数*/
int InitSockets(void)
{
    WSADATA wsaData;
    WORD sockVersion;
    int err;

    /*设置Winsock版本号*/
    sockVersion = MAKEWORD( 2, 2 );
    /*初始化Winsock*/
    err = WSAStartup( sockVersion, &wsaData );
    /*如果初始化失败*/
    if ( err != 0 )
    {
      printf("Error %d: Winsock not available\n", err);
      return 1;
    }
    return 0;
}


/*获取选项函数*/
void GetArgments(int argc, char **argv)
{
    int i;
    for(i=1; i < argc ;i++)
    {
        /*参数的第一个字符若是“-”*/
        if (argv[i][0] == '-')
        {
            /*转换成小写*/
            switch (tolower(argv[i][1]))
            {
                /*若是端口号*/
                case 'p': 
                    if (strlen(argv[i]) > 3)
                        port = atoi(&argv[i][3]);
                    break;
               /*若是主机名*/
               case 'h': 
                    hostName = &argv[i][3];
                    break;
                /*最多服务次数*/
                case 'n': 
                    maxService = atoi(&argv[i][3]);
                    break;
                /*其他情况*/
                default:
                    userHelp();
                    break;
            }
        }
    }
    return;
}

/*错误输出函数*/
void ErrorPrint(x)
{ 
    printf("Error %d: %s\n", WSAGetLastError(), x);
}

/*用户帮助函数*/
void userHelp()
{
    printf("userHelp:  -h:str -p:int -n:int\n");
    printf("           -h:str  The host name \n");
    printf("                   The default host is 127.0.0.1\n");
    printf("           -p:int  The Port number to use\n");
    printf("                   The default port is 9999\n");
    printf("           -n:int  The number of service,below MAX_SER \n");
    printf("                   The default number is 3\n");
    ExitProcess(-1);
}

/*循环控制函数*/
int LoopControl(SOCKET listenfd, int isMultiTasking)
{
    SOCKET acceptfd;
    struct sockaddr_in clientAddr;
    int err;
    int nSize;
    int serverNum = 0;
    HANDLE handles[MAX_SER];
    int myID;
    
    /*服务次数小于最大服务次数*/
    while (serverNum < maxService)
    {
      nSize = sizeof(clientAddr);
      /*接收客户端请求*/
      acceptfd = accept(listenfd, (struct sockaddr *)
                         &clientAddr, &nSize);
      /*如果接收失败*/
      if (acceptfd == INVALID_SOCKET)
      {
          ErrorPrint("Error: accept failed\n");
          return 1;
      }
      /*接收成功*/
      printf("Accepted connection from client at %s\n",
             inet_ntoa(clientAddr.sin_addr));
      /*如果允许多任务执行*/
      if (isMultiTasking) 
      {
          /*创建一个新线程来执行任务,新线程的初始堆栈大小为1000,线程执行函数
          是Service(),传递给Service()的参数为acceptfd*/
          handles[serverNum] = CreateThread(NULL, 1000,
                      (LPTHREAD_START_ROUTINE)Service,
                      (LPVOID) acceptfd, 0, &myID);

       }
      else
          /*直接调用服务客户端的函数*/
          Service((LPVOID) acceptfd);
      serverNum++;
    }

    if (isMultiTasking)
    {
        /*在一个线程中等待多个事件,当所有对象都被通知时函数才会返回,并且等待没有时间限制*/
        err = WaitForMultipleObjects(maxService, handles, TRUE, INFINITE);
        printf("Last thread to finish was thread #%d\n", err);

     }
    return 0;
}

/*服务函数*/
void Service(LPVOID lpv)
{
    SOCKET acceptfd = (SOCKET) lpv;
    const char *msg = "HELLO CLIENT";
    char response[4096];

    /*用0初始化response[4096]数组*/
    memset(response, 0, sizeof(response));
    /*接收数据,存入response中*/
    recv(acceptfd, response, sizeof(response), 0);

    /*如果接收到的数据和预定义的数据不同*/
    if (strcmp(response, "HELLO SERVER")) 
    {
        printf("Application:  client not using expected "
            "protocol %s\n", response);
    }
    else
        /*发送服务器端信息到客户端*/
        send (acceptfd, msg, strlen(msg)+1, 0);
    /*关闭套接字*/
    closesocket(acceptfd);
}


/*主函数*/
int main(int argc, char **argv)
{
    SOCKET listenfd;
    int err;
    struct sockaddr_in serverAddr;
    struct hostent *ptrHost;
    initial();
    GetArgments(argc,argv);
    InitSockets();
    /*创建TCP流套接字,在domain参数为PF_INET的SOCK_STREAM套接口中,protocol参数为0意味
    着告诉内核选择 IPPRPTP_TCP,这也意味着套接口将使用TCP/IP协议*/
    listenfd = socket(PF_INET, SOCK_STREAM, 0);
    /*如果创建套接字失败*/
    if (listenfd == INVALID_SOCKET)
    {
        printf("Error: out of socket resources\n");
        return 1;
    }

    /*如果是IP地址*/
    if (atoi(hostName)) 
    {
        /*将IP地址转换成32二进制表示法,返回32位二进制的网络字节序*/
        u_long ip_addr = inet_addr(hostName);
        /*根据IP地址找到与之匹配的主机名*/
        ptrHost = gethostbyaddr((char *)&ip_addr,
                     sizeof(u_long), AF_INET);
     }
    /*如果是主机名*/
    else
        /*根据主机名获取一个指向hosten的指针,该结构中包含了该主机所有的IP地址*/
        ptrHost = gethostbyname(hostName);

    /*如果解析失败*/
    if (!ptrHost)
    {
        ErrorPrint("cannot resolve hostname");
        return 1;
    }
    
    /*设置服务器地址*/
    /*设置地址族为PF_INET*/
    serverAddr.sin_family = PF_INET;
    /*将一个通配的Internet地址转换成无符号长整型的网络字节序数*/
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    /*将端口号转换成无符号短整型的网络字节序数*/
    serverAddr.sin_port = htons(port);
    
    /*将套接字与服务器地址绑定*/
    err = bind(listenfd, (const struct sockaddr *) &serverAddr,
               sizeof(serverAddr));
    /*如果绑定失败*/
    if (err == INVALID_SOCKET)
    {
        ErrorPrint("Error: unable to bind socket\n");
        return 1;
    }
    
    /*开始侦听,设置等待连接的最大队列长度为SOMAXCONN,默认值为5个*/
    err = listen(listenfd, SOMAXCONN);
    /*如果侦听失败*/
    if (err == INVALID_SOCKET)
    {
        ErrorPrint("Error: listen failed\n");
        return 1;
    }
    
    LoopControl(listenfd, 1);
    printf("Server is down\n");
    /*释放Winscoket初始化时占用的资源*/
    WSACleanup();
    return 0;
}




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -