• WinSock编程(TCP)


    WinSocket编程一般步骤-服务器端

    第一步:包含WinSocket的头文件和动态链接库

    #include <WinSock2.h>
    #pragma comment(lib, "ws2_32.lib")
    

    第二步:初始化WSAStartup

    WSADATA wsaData;
    int nRes = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (0 != nRes)
    {
    	std::cout<<"WSAStartup Failed!"<<std::endl;
    	WSACleanup();
    	return -1;
    }
    

    第三步:创建一个SOCKET,Create a SOCKET for listen for incoming connection requests

    // Create a SOCKET for listen for incoming connection requests
    SOCKET ListenSocket;
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (INVALID_SOCKET == ListenSocket)
    {
    	std::cout<<"socket Failed!"<<std::endl;
    	WSACleanup();
    	return -1;
    }
    

    第三步:绑定监听SOCKET(ListenSocket)与本地地址(Local Address)

    SOCKADDR_IN  ServAddr;
    ServAddr.sin_family = AF_INET;
    ServAddr.sin_addr.s_addr = INADDR_ANY;
    ServAddr.sin_port = htons(DEFAULT_PORT);
    // bind 
    // The bind function associates a local address with a socket.
    nRet = bind(ListenSocket, (SOCKADDR*)&ServAddr, sizeof(ServAddr));
    if (0 != nRet)
    {
    	std::cout<<"bind Failed!"<<std::endl;
    	WSACleanup();
    	closesocket(ListenSocket);
    	return -1;
    }
    

    第四步:监听listen

    // listen
    // Listen for incoming connection requests 
    // on the created socket
    nRes = listen(ListenSocket, DEFAULT_MAX_LISTEN);
    if (0 != nRes)
    {
    	std::cout<<"listen Failed!"<<std::endl;
    	WSACleanup();
    	closesocket(ListenSocket);
    	return -1;
    }
    

    第五步:接受连接请求accept

    // accept
    // The accept function permits an incoming connection attempt on a socket.
    int nLen = sizeof(ClientAddr);
    AcceptSocket = accept(ListenSocket, (sockaddr*)&ClientAddr, &nLen);
    if (INVALID_SOCKET == AcceptSocket)
    {
    	std::cout<<"accept Failed!"<<std::endl;
    	WSACleanup();
    	closesocket(ListenSocket);
    	return -1;
    }
    

    第六步:接收客户端数据recv,如果accept成功,recv消息;如果accept不成功,则不recv消息

    ZeroMemory(g_RecvBuf, DEFAULT_BUFLEN);
    nByteLen = recv(AcceptSocket, g_RecvBuf, DEFAULT_BUFLEN+1, 0);
    if ((0 == strcmp(g_RecvBuf, "quit")) || (0 == strcmp(g_RecvBuf, "QUIT")))
    {
    	std::cout<<"Client QUIT!"<<std::endl;
    	WSACleanup();
    	closesocket(ListenSocket);
    	closesocket(AcceptSocket);
    	return 0;
    }
    if (0 == nByteLen)
    {
    	std::cout<<"Client QUIT!"<<std::endl;
    	WSACleanup();
    	closesocket(ListenSocket);
    	closesocket(AcceptSocket);
    	return 0;
    }
    if (SOCKET_ERROR == nByteLen)
    {
    	std::cout<<"recv Failed!"<<std::endl;
    	WSACleanup();
    	closesocket(ListenSocket);
    	closesocket(AcceptSocket);
    	return -1;
    }
    std::cout<<"Client : "<<g_RecvBuf<<std::endl;
    

    第七步(可选):Send消息至客户端

    // send data to the client
    // The send function sends data on a connected socket.
    ZeroMemory(g_SendBuf, DEFAULT_BUFLEN);
    std::cout<<"> ";
    gets(g_SendBuf);
    if ((0 == strcmp(g_SendBuf, "quit")) || (0 == strcmp(g_SendBuf, "QUIT")))
    {
    	std::cout<<"Server QUIT!"<<std::endl;
    	WSACleanup();
    	closesocket(ListenSocket);
    	closesocket(AcceptSocket);
    	return 0;
    }
    nByteLen = send(AcceptSocket, g_SendBuf, strlen(g_SendBuf)+ 1, 0);
    if (SOCKET_ERROR == nByteLen)
    {
    	std::cout<<"send Failed!"<<std::endl;
    	WSACleanup();
    	closesocket(AcceptSocket);
    	closesocket(ListenSocket);
    	return -1;
    }
    std::cout<<"Server : "<<g_SendBuf<<std::endl;
    

    如果需要连续不断地和客户端进行交互的话,则可以将send和recv两个步骤绑定在一起,放在一个while(true)循环中,直到服务器或者客户端某一方退出。

    代码实例如下:

    while (true)
    {
    	// receive the data from client
    	ZeroMemory(g_RecvBuf, DEFAULT_BUFLEN);
    	nByteLen = recv(AcceptSocket, g_RecvBuf, DEFAULT_BUFLEN+1, 0);
    	if ((0 == strcmp(g_RecvBuf, "quit")) || (0 == strcmp(g_RecvBuf, "QUIT")))
    	{
    		std::cout<<"Client QUIT!"<<std::endl;
    		WSACleanup();
    		closesocket(ListenSocket);
    		closesocket(AcceptSocket);
    		return 0;
    	}
    	if (0 == nByteLen)
    	{
    		std::cout<<"Client QUIT!"<<std::endl;
    		WSACleanup();
    		closesocket(ListenSocket);
    		closesocket(AcceptSocket);
    		return 0;
    	}
    	if (SOCKET_ERROR == nByteLen)
    	{
    		std::cout<<"recv Failed!"<<std::endl;
    		WSACleanup();
    		closesocket(ListenSocket);
    		closesocket(AcceptSocket);
    		return -1;
    	}
    
            std::cout<<"Client : "<<g_RecvBuf<<std::endl;
    
    	// send data to the client
    	// The send function sends data on a connected socket.
    	ZeroMemory(g_SendBuf, DEFAULT_BUFLEN);
    	std::cout<<"> ";
    	gets(g_SendBuf);
    	if ((0 == strcmp(g_SendBuf, "quit")) || (0 == strcmp(g_SendBuf, "QUIT")))
    	{
    		std::cout<<"Server QUIT!"<<std::endl;
    		WSACleanup();
    		closesocket(ListenSocket);
    		closesocket(AcceptSocket);
    		return 0;
    	}
    	nByteLen = send(AcceptSocket, g_SendBuf, strlen(g_SendBuf)+ 1, 0);
    	if (SOCKET_ERROR == nByteLen)
    	{
    		std::cout<<"send Failed!"<<std::endl;
    		WSACleanup();
    		closesocket(AcceptSocket);
    		closesocket(ListenSocket);
    		return -1;
    	}
    	std::cout<<"Server : "<<g_SendBuf<<std::endl;
    }
    

    第八步:清理已生成的SOCKET并退出。

    WSACleanup();
    closesocket(ListenSocket);
    closesocket(AcceptSocket);
    return 0;
    

    由于前面的所有步骤中,都对异常以及正常退出的情况作出了处理,因此最后清理这个步骤其实也是可选的。

  • 相关阅读:
    常见浏览器的兼容问题
    SCSS 的理解
    常见浏览器兼容性问题与解决方案(上)
    常见浏览器兼容性问题与解决方案(下)
    ie6定位absolute bug触发layout解决
    AngularJS 最常用的八种功能
    IE6的3像素bug
    CSS属性级Hack
    什么是SASS
    什么是less?
  • 原文地址:https://www.cnblogs.com/Jasonscor/p/3309414.html
Copyright © 2020-2023  润新知