2.1.2 小试牛刀--模拟实现Windows的TCP程序(5)
⑤ 服务模块
此模块的功能是通过函数Service()实现的,功能是实现接收、判断来自客户端的数据,并发送数据到客户端。具体代码如下:
- /*服务函数*/
- 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;
- }