zoukankan      html  css  js  c++  java
  • 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;
    

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

  • 相关阅读:
    【NOIP2016提高组】 Day1 T3 换教室
    【NOIP2016 Day1 T2】天天爱跑步
    web@前端--html,css,javascript简介、第一个页面(常用标签简介)
    MySQL--视图view、触发器trigger、事务(start transaction)、存储过程(特殊的数据逻辑处理函数)、流程控制(if,case....)
    MySQL--pymysql模块
    MySQL--(了解)可能会用到的内置函数
    MySQL--详细查询操作(单表记录查询、多表记录查询(连表查询)、子查询)
    MySQL--表操作(约束条件foreign key关联表 多对1,多对多,1对1)
    MySQL--表操作(innodb表字段数据类型、约束条件)、sql_mode操作
    MySQL基本语句、存储引擎
  • 原文地址:https://www.cnblogs.com/Jasonscor/p/3309414.html
Copyright © 2011-2022 走看看