网络编程

Posted by Mr.Be1ieVe on Monday, January 1, 0001

3/9

image-20200309113441335

image-20200309113925329

非阻塞模式

// 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

image-20200323111552979

image-20200323113425859

3/30

image-20200330140139366

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

非阻塞:并发强

模型

image-20200330140556146

image-20200330140713774

image-20200330140911046

4/13

image-20200413135556939

4/20

image-20200420113827282

5/11

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

「真诚赞赏,手留余香」

Mr.Be1ieVe's Treasure

真诚赞赏,手留余香

使用微信扫描二维码完成支付