网络编程

3/9

非阻塞模式

// TcpServer.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <WINSOCK2.H>   
#include <iostream>

#pragma comment(lib,"WS2_32.lib")   
#define BUF_SIZE    64      // 缓冲区大小

int _tmain(int argc, _TCHAR* argv[])
{
    WSADATA wsd;                    // WSADATA变量,用于初始化Windows Socket   
    SOCKET  sServer;                    // 服务器套接字,用于监听客户端请求
    SOCKET  sClient;                    // 客户端套接字,用于实现与客户端的通信   
    int     retVal;                        // 调用各种Socket函数的返回值   
    char    buf[BUF_SIZE];            // 用于接受客户端数据的缓冲区   

    // 初始化套接字动态库   
    if(WSAStartup(MAKEWORD(2,2),&wsd) != 0)   
    {   
        printf("WSAStartup failed !\n");   
        return 1;   
    }     
    // 创建用于监听的套接字   
    sServer = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);   
    unsigned long iMode = 1;
    retVal = ioctlsocket(sServer, FIONBIO, &iMode);
    if(INVALID_SOCKET == sServer)   
    {   
        printf("socket failed !\n");   
        WSACleanup();   
        return -1;   
    }     

    // 设置服务器套接字地址   
    SOCKADDR_IN addrServ;   
    addrServ.sin_family = AF_INET;   
    addrServ.sin_port = htons(9990);        // 监听端口为9990
    addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);    
    // 绑定套接字sServer到本地地址,端口9990  
    retVal = bind(sServer,(const struct sockaddr*)&addrServ,sizeof(SOCKADDR_IN));   

    if(SOCKET_ERROR == retVal)   
    {   
        printf("bind failed !\n");   
        closesocket(sServer);   
        WSACleanup();   
        return -1;   
    }     
    // 监听套接字   
    retVal = listen(sServer,1);   
    if(SOCKET_ERROR == retVal)   
    {   
        printf("listen failed !\n");   
        closesocket(sServer);   
        WSACleanup();   
        return -1;   
    }     
    // 接受客户请求   
    printf("TCP Server start...\n");
    sockaddr_in addrClient;                            // 客户端地址
    int addrClientlen = sizeof(addrClient);   
    while (true)
    {
        sClient = accept(sServer, (sockaddr FAR*) & addrClient, &addrClientlen);
        if (INVALID_SOCKET == sClient)
        {
            int err = WSAGetLastError();
            if (err == WSAEWOULDBLOCK)
            {
                Sleep(100);
                continue;
            }
            else
            {
                printf("accept failed!\n");
                closesocket(sServer);
                WSACleanup();
                return -1;
            }
        }
        break;

    }

    // 循环接收客户端的数据,直接客户端发送quit命令后退出。  
    while(true)
    {
        ZeroMemory(buf,BUF_SIZE);                        // 清空接收数据的缓冲区
        retVal = recv(sClient,buf,BUFSIZ,0);                // 
        if(SOCKET_ERROR == retVal )   
        {   
            int err = WSAGetLastError();
            if (err == WSAEWOULDBLOCK)
            {
                Sleep(100);
                continue;
            }
            else if (err == WSAETIMEDOUT || err == WSAENETDOWN)
            {
                printf("recv failed!\n");
                closesocket(sServer);
                closesocket(sClient);
                WSACleanup();
                return -1;
            }

        } 
        if (buf == NULL)
            continue;
        // 获取当前系统时间
        SYSTEMTIME st;
        GetLocalTime(&st);
        char sDateTime[30];
        sprintf(sDateTime, "%4d-%2d-%2d %2d:%2d:%2d",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);
        // 打印输出的信息
        printf("%s, Recv From Client [%s:%d] :%s\n", sDateTime, inet_ntoa(addrClient.sin_addr), addrClient.sin_port, buf);   
        // 如果客户端发送quit字符串,则服务器退出
        if(strcmp(buf, "quit") == 0)
        {
            retVal = send(sClient,"quit",strlen("quit"),0);   
            break;
        }
        else        // 否则向客户端发送回显字符串
        {
            char    msg[BUF_SIZE];  
            sprintf(msg, "Message received - %s", buf); 
            retVal = send(sClient, msg, strlen(msg),0);   
            if(SOCKET_ERROR == retVal)   
            {   
                   printf("send failed !\n");   
                 closesocket(sServer);   
                   closesocket(sClient);   
                   WSACleanup();   
                   return -1;   
            }   
        }
    }
    // 释放套接字   
    closesocket(sServer);   
    closesocket(sClient);   
    WSACleanup();   
    // 暂停,按任意键退出
    system("pause");
    return 0;
}
// TcpClient.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <Winsock2.H>   
#include <string>
#include <iostream>

#pragma comment(lib,"WS2_32.lib")   
#define BUF_SIZE    64          // 缓冲区大小  

int _tmain(int argc, _TCHAR* argv[])
{
    WSADATA     wsd;                    // 用于初始化Windows Socket   
    SOCKET      sHost;                    // 与服务器进行通信的套接字   
    SOCKADDR_IN servAddr;            // 服务器地址   
    char        buf[BUF_SIZE];            // 用于接受数据缓冲区   
    int         retVal;                            // 调用各种Socket函数的返回值   
    // 初始化Windows Socket
    if(WSAStartup(MAKEWORD(2,2),&wsd) != 0)   
    {   
        printf("WSAStartup failed !\n");   
        return 1;   
    }     
    // 创建套接字   
    sHost = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);   
    if(INVALID_SOCKET == sHost)   
    {   
        printf("socket failed !\n");   
        WSACleanup();   
        return -1;   
    }    
    // 设置服务器地址   
    servAddr.sin_family = AF_INET;   
    servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");        // 用户需要根据实际情况修改
    servAddr.sin_port = htons(9990);                                                    // 在实际应用中,建议将服务器的IP地址和端口号保存在配置文件中
    int sServerAddlen = sizeof(servAddr);                                                // 计算地址的长度       
    // 连接服务器   
    while (true)
    {
        retVal = connect(sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr));
        if (SOCKET_ERROR == retVal)
        {
            int err = WSAGetLastError();
            if (err == WSAEWOULDBLOCK || err == WSAEINVAL)
            {
                Sleep(500);
                continue;
            }
            else if (err == WSAEISCONN)
            {
                break;
            }
            else
            {
                printf("connect failed !\n");
                closesocket(sHost);
                WSACleanup();
                return -1;
            }
        }
    }

    // 循环向服务器发送字符串,并显示反馈信息。
    // 发送quit将使服务器程序退出,同时客户端程序自身也将退出
    while(true)
    {
        // 向服务器发送数据   
        printf("Please input a string to send: ");
        // 接收输入的数据
        std::string str;
        std::getline(std::cin, str);
        // 将用户输入的数据复制到buf中
        ZeroMemory(buf,BUF_SIZE);   
        strcpy(buf,str.c_str());   
        if(buf[0]=='\0')
            continue;
        // 向服务器发送数据
        while (true)
        {
            retVal = send(sHost, buf, strlen(buf), 0);
            //retVal = WSASend(sHost, buf, BUF_SIZE, strlen(buf),0,NULL,NULL);
            if (SOCKET_ERROR == retVal)
            {
                int err = WSAGetLastError();
                if (err == WSAEWOULDBLOCK)
                {
                    Sleep(500);
                    continue;
                }
                else
                {
                    printf("send failed!\n");
                    closesocket(sHost);
                    WSACleanup();
                    return -1;
                }
            }
            break;
        }
        // 接收服务器回传的数据  
        while (true)
        {
            ZeroMemory(buf, BUF_SIZE);
            retVal = recv(sHost, buf, sizeof(buf) + 1, 0);
            if (SOCKET_ERROR == retVal)
            {
                int err = WSAGetLastError();
                if (err == WSAEWOULDBLOCK)
                {
                    Sleep(100);
                    printf("waiting back msg!\n");
                    continue;
                }
                else if (err == WSAETIMEDOUT || err == WSAENETDOWN)
                {
                    printf("recv failed!\n");
                    closesocket(sHost);
                    WSACleanup();
                    return -1;
                }
                break;
            }
            break;
        }
        printf("Recv From Server: %s\n",buf);   
        // 如果收到quit,则退出
        if(strcmp(buf, "quit") == 0)
        {
            printf("quit!\n");
            break;
        }
    }
    // 释放资源   
    closesocket(sHost);   
    WSACleanup();   
    // 暂停,按任意键继续
    system("pause");
    return 0;  
}

3/23

3/30

阻塞:适合通信量较少的简单应用,没有完成之前不会返回

非阻塞:并发强

模型

4/13

4/20

5/11

用户类打交道最多的是View视图类,对界面各种操作响应


专业学习      专业学习

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

商业计划书撰写及案例分析 上一篇
TCPIP复习 下一篇