1 服务器端

由先得专门为服务器端做一个Socket通信类CNewSocket类,此类继承CAsyncSocket类,专门负责服务器端socket通信事情:

NewSocket.h:

#pragma once
#include "afxsock.h"
//此类专门用来与客户端进行socket通信
class CNewSocket :public CAsyncSocket
{
public:CNewSocket(void);~CNewSocket(void);virtual void OnReceive(int nErrorCode);virtual void OnSend(int nErrorCode);// 消息长度UINT m_nLength;//消息缓冲区char m_szBuffer[4096];
};

对应实现代码如下:

NewSocket.cpp:

#include "StdAfx.h"
#include "NewSocket.h"CNewSocket::CNewSocket(void): m_nLength(0)
{memset(m_szBuffer,0,sizeof(m_szBuffer));
}CNewSocket::~CNewSocket(void)
{if(m_hSocket !=INVALID_SOCKET){Close();}
}void CNewSocket::OnReceive(int nErrorCode)
{// TODO: Add your specialized code here and/or call the base classm_nLength =Receive(m_szBuffer,sizeof(m_szBuffer),0); //接收数据m_szBuffer[m_nLength] ='\0';//接收消息后就开始给客户端发相同的消息AsyncSelect(FD_WRITE); //触发OnSend函数CAsyncSocket::OnReceive(nErrorCode);
}void CNewSocket::OnSend(int nErrorCode)
{// TODO: Add your specialized code here and/or call the base classchar m_sendBuf[4096];    //消息缓冲区strcpy(m_sendBuf,"server send:");strcat(m_sendBuf,m_szBuffer);Send(m_sendBuf,strlen(m_sendBuf));//触发OnReceive函数AsyncSelect(FD_READ);CAsyncSocket::OnSend(nErrorCode);
}

如上,NewSocket类重载了CAsyncSocket类的接收与发送事件处理例程,一旦被触发了发送或接收事件,将调用此对应函数.

接下来服务器端在做一个专门类CListenSocket类,用来监听来自客户端的连接请求,如下:

ListenSocket.h:

#pragma once
#include "afxsock.h"
#include "NewSocket.h"
class CListenSocket :public CAsyncSocket
{
public:CListenSocket(void);~CListenSocket(void);CNewSocket *m_pSocket; //指向一个连接的socket对象virtual void OnAccept(int nErrorCode);
};

由上可知,CListenSocket类还是继承了CAsyncSocket类,并重载了其接受事件,且包含了一个由之前定义好的CNewSocket类指针做为成员,用来指向与客户端连接好的连接.
其实现代码如下:

ListenSocket.cpp:

#include "StdAfx.h"
#include "ListenSocket.h"CListenSocket::CListenSocket(void)
{
}CListenSocket::~CListenSocket(void)
{
}void CListenSocket::OnAccept(int nErrorCode)
{// TODO: Add your specialized code here and/or call the base classCNewSocket *pSocket =new CNewSocket();if(Accept(*pSocket)){pSocket->AsyncSelect(FD_READ); //触发通信socket的Read函数读数据m_pSocket =pSocket;}else{delete pSocket;}CAsyncSocket::OnAccept(nErrorCode);
}

这个OnAccept事件触发是在Listen之后,如果有客户端尝试连接时触发,且先看后续内容.

接下来就是对话框的代码了:

SocketServerDlg.h:

// SocketServerDlg.h : header file
//#pragma once
#include "ListenSocket.h"// CSocketServerDlg dialog
class CSocketServerDlg : public CDialogEx
{
// Construction
public:CSocketServerDlg(CWnd* pParent = NULL); // standard constructor// Dialog Dataenum { IDD = IDD_SOCKETSERVER_DIALOG };protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV supportCListenSocket m_srvrSocket; //监听套接字
// Implementation
protected:HICON m_hIcon;// Generated message map functionsvirtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()
public:afx_msg void OnBnClickedBtStart();
};

在这个CSocketServerDlg类的声明内包含了一个CListenSocket成员m_srvrSocket,并有一个start按键.

// SocketServerDlg.cpp : implementation file
//#include "stdafx.h"
#include "SocketServer.h"
#include "SocketServerDlg.h"
#include "afxdialogex.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif// CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialogEx
{
public:CAboutDlg();// Dialog Dataenum { IDD = IDD_ABOUTBOX };protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support// Implementation
protected:DECLARE_MESSAGE_MAP()
};CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()// CSocketServerDlg dialogCSocketServerDlg::CSocketServerDlg(CWnd* pParent /*=NULL*/): CDialogEx(CSocketServerDlg::IDD, pParent)
{m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CSocketServerDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CSocketServerDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BT_START, &CSocketServerDlg::OnBnClickedBtStart)
END_MESSAGE_MAP()// CSocketServerDlg message handlersBOOL CSocketServerDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// Set the icon for this dialog.  The framework does this automatically//  when the application's main window is not a dialogSetIcon(m_hIcon, TRUE);         // Set big iconSetIcon(m_hIcon, FALSE);     // Set small icon// TODO: Add extra initialization herereturn TRUE;  // return TRUE  unless you set the focus to a control
}void CSocketServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialogEx::OnSysCommand(nID, lParam);}
}// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.void CSocketServerDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}
}// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSocketServerDlg::OnQueryDragIcon()
{return static_cast<HCURSOR>(m_hIcon);
}void CSocketServerDlg::OnBnClickedBtStart()
{// TODO: Add your control notification handler code hereif(m_srvrSocket.m_hSocket ==INVALID_SOCKET){//创建监听套接字,激发FD_ACCEPT事件,默认端口7190BOOL bFlag =m_srvrSocket.Create(7190,SOCK_STREAM,FD_ACCEPT);    //第三个参数表示m_srvrSocket只对FD_ACCEPT事件感兴趣if(!bFlag){AfxMessageBox(_T("Socket创建失败!"));m_srvrSocket.Close();PostQuitMessage(0);return;}GetDlgItem(IDC_BT_START)->EnableWindow(FALSE);//监听成功,等待连接请求if(!m_srvrSocket.Listen())//如果监听失败{int nErrorCode =m_srvrSocket.GetLastError();   //检测错误信息if(nErrorCode !=WSAEWOULDBLOCK)                //如果不是线程阻塞{AfxMessageBox(_T("Socket错误!"));m_srvrSocket.Close();PostQuitMessage(0);return;}}}
}

当用户按下start按键时,程序首先调用m_srvrSocket的Create函数创建一个socket,然后调用它的Listen函数监听客户端的连接请求,一旦客户端尝试连接服务器,那将触发m_srvrSocket的FD_ACCEPT事件.接着在m_srvrSocket的OnAccept函数内,将创建一个CNewSocket对象,并利用此对象来操作socket收发,到此,服务器端的代码完.

2 客户端

这里的客户端的功能就是与服务器建立连接,交用户的数据发送给服务器,并显示来自服务器的接收数据.

与服务器类似,首先做一个专门用于socket通信的类ClientSocket类:

ClientSocket.h:

#pragma once
#include "afxsock.h"
class ClientSocket :public CAsyncSocket
{
public:ClientSocket(void);~ClientSocket(void);// 是否连接bool m_bConnected;// 消息长度UINT m_nLength;//消息缓冲区char m_szBuffer[5096];virtual void OnConnect(int nErrorCode);virtual void OnReceive(int nErrorCode);virtual void OnSend(int nErrorCode);
};

由上类声明可知,此类重载了CAsyncSocket的连接,接收,发送事件例程.其实现代码如下:

#include "StdAfx.h"
#include "ClientSocket.h"
#include "SocketTest.h"
#include "SocketTestDlg.h"ClientSocket::ClientSocket(void): m_bConnected(false), m_nLength(0)
{memset(m_szBuffer,0,sizeof(m_szBuffer));
}ClientSocket::~ClientSocket(void)
{if(m_hSocket !=INVALID_SOCKET){Close();}
}void ClientSocket::OnConnect(int nErrorCode)
{// TODO: Add your specialized code here and/or call the base class//连接成功if(nErrorCode ==0){m_bConnected =TRUE;//获取主程序句柄CSocketTestApp *pApp =(CSocketTestApp *)AfxGetApp();//获取主窗口CSocketTestDlg *pDlg =(CSocketTestDlg *)pApp->m_pMainWnd;//在主窗口输出区显示结果CString strTextOut;strTextOut.Format(_T("already connect to "));strTextOut +=pDlg->m_Address;strTextOut += _T("    端口号:");CString str;str.Format(_T("%d"),pDlg->m_Port);strTextOut +=str;pDlg->m_MsgR.InsertString(0,strTextOut);//激活一个网络读取事件,准备接收AsyncSelect(FD_READ);}CAsyncSocket::OnConnect(nErrorCode);
}void ClientSocket::OnReceive(int nErrorCode)
{// TODO: Add your specialized code here and/or call the base class//获取socket数据m_nLength =Receive(m_szBuffer,sizeof(m_szBuffer));//获取主程序句柄CSocketTestApp *pApp =(CSocketTestApp *)AfxGetApp();//获取主窗口CSocketTestDlg *pDlg =(CSocketTestDlg *)pApp->m_pMainWnd;CString strTextOut(m_szBuffer);//在主窗口的显示区显示接收到的socket数据pDlg->m_MsgR.InsertString(0,strTextOut);memset(m_szBuffer,0,sizeof(m_szBuffer));CAsyncSocket::OnReceive(nErrorCode);
}void ClientSocket::OnSend(int nErrorCode)
{// TODO: Add your specialized code here and/or call the base class//发送数据Send(m_szBuffer,m_nLength,0);m_nLength =0;memset(m_szBuffer,0,sizeof(m_szBuffer));//继续提请一个读的网络事件,接收socket消息AsyncSelect(FD_READ);CAsyncSocket::OnSend(nErrorCode);
}

接下来就是对话框代码了:

SocketTestDlg.h:

// SocketTestDlg.h : header file
//#pragma once
#include "afxwin.h"
#include "ClientSocket.h"// CSocketTestDlg dialog
class CSocketTestDlg : public CDialogEx
{
// Construction
public:CSocketTestDlg(CWnd* pParent = NULL);   // standard constructor// Dialog Dataenum { IDD = IDD_SOCKETTEST_DIALOG };protected:virtual void DoDataExchange(CDataExchange* pDX);   // DDX/DDV support// Implementation
protected:HICON m_hIcon;// Generated message map functionsvirtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()
public:// 服务器IP地址CString m_Address;// 服务器端口号int m_Port;// 消息接收显示控件CListBox m_MsgR;afx_msg void OnBnClickedBtClear();afx_msg void OnBnClickedOk();// 用户输入的即将发送的内容CString m_MsgS;afx_msg void OnBnClickedBtConnect();afx_msg void OnTimer(UINT_PTR nIDEvent);// 连接服务器次数int m_nTryTimes;ClientSocket m_ClientSocket;afx_msg void OnBnClickedBtSend();afx_msg void OnBnClickedBtClose();
};

其实现代码如下:

// SocketTestDlg.cpp : implementation file
//#include "stdafx.h"
#include "SocketTest.h"
#include "SocketTestDlg.h"
#include "afxdialogex.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif// CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialogEx
{
public:CAboutDlg();// Dialog Dataenum { IDD = IDD_ABOUTBOX };protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support// Implementation
protected:DECLARE_MESSAGE_MAP()
};CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()// CSocketTestDlg dialogCSocketTestDlg::CSocketTestDlg(CWnd* pParent /*=NULL*/): CDialogEx(CSocketTestDlg::IDD, pParent), m_Address(_T("127.0.0.1")), m_Port(0), m_MsgS(_T("")), m_nTryTimes(0)
{m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CSocketTestDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);DDX_Text(pDX, IDC_ET_IPADDRESS, m_Address);DDX_Text(pDX, IDC_ET_PORT, m_Port);DDX_Control(pDX, IDC_LIST_R, m_MsgR);DDX_Text(pDX, IDC_ET_SEND, m_MsgS);
}BEGIN_MESSAGE_MAP(CSocketTestDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BT_CLEAR, &CSocketTestDlg::OnBnClickedBtClear)ON_BN_CLICKED(IDOK, &CSocketTestDlg::OnBnClickedOk)ON_BN_CLICKED(IDC_BT_CONNECT, &CSocketTestDlg::OnBnClickedBtConnect)ON_WM_TIMER()ON_BN_CLICKED(IDC_BT_SEND, &CSocketTestDlg::OnBnClickedBtSend)ON_BN_CLICKED(IDC_BT_CLOSE, &CSocketTestDlg::OnBnClickedBtClose)
END_MESSAGE_MAP()// CSocketTestDlg message handlersBOOL CSocketTestDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// Set the icon for this dialog.  The framework does this automatically//  when the application's main window is not a dialogSetIcon(m_hIcon, TRUE);         // Set big iconSetIcon(m_hIcon, FALSE);     // Set small icon// TODO: Add extra initialization herereturn TRUE;  // return TRUE  unless you set the focus to a control
}void CSocketTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialogEx::OnSysCommand(nID, lParam);}
}// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.void CSocketTestDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}
}// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSocketTestDlg::OnQueryDragIcon()
{return static_cast<HCURSOR>(m_hIcon);
}void CSocketTestDlg::OnBnClickedBtClear()
{// TODO: Add your control notification handler code herem_MsgR.ResetContent();
}void CSocketTestDlg::OnBnClickedOk()
{// TODO: Add your control notification handler code here/*CDialogEx::OnOK();*/UpdateData(TRUE);if(m_MsgS.IsEmpty()){AfxMessageBox(_T("please type the message you want to send!"));return;}
}void CSocketTestDlg::OnBnClickedBtConnect()
{// TODO: Add your control notification handler code here//如果当前已经与服务器建立了连接,则直接返回if(m_ClientSocket.m_bConnected){AfxMessageBox(_T("当前已经与服务器建立连接"));return;}UpdateData(TRUE);if(m_Address.IsEmpty()){AfxMessageBox(_T("服务器的IP地址不能为空!"));return;}if(m_Port <=1024){AfxMessageBox(_T("服务器的端口设置非法!"));return;}//使Connect按键失能GetDlgItem(IDC_BT_CONNECT)->EnableWindow(FALSE);//启动连接定时器,每1秒中尝试一次连接SetTimer(1,1000,NULL);
}void CSocketTestDlg::OnTimer(UINT_PTR nIDEvent)
{// TODO: Add your message handler code here and/or call defaultif(m_ClientSocket.m_hSocket ==INVALID_SOCKET){BOOL bFlag =m_ClientSocket.Create(0,SOCK_STREAM,FD_CONNECT); //创建套接字if(!bFlag){AfxMessageBox(_T("Socket创建失败!"));m_ClientSocket.Close();PostQuitMessage(0);//退出return;}}m_ClientSocket.Connect(m_Address,m_Port); //连接服务器if(m_nTryTimes >=10){KillTimer(1);AfxMessageBox(_T("连接失败!"));GetDlgItem(IDC_BT_CONNECT)->EnableWindow(TRUE);return;}else if(m_ClientSocket.m_bConnected){KillTimer(1);GetDlgItem(IDC_BT_CONNECT)->EnableWindow(TRUE);return;}CString strTextOut =_T("尝试连接服务器第");m_nTryTimes ++;CString str;str.Format(_T("%d"),m_nTryTimes);strTextOut +=str;strTextOut +=_T("次...");m_MsgR.InsertString(0,strTextOut);CDialogEx::OnTimer(nIDEvent);
}void CSocketTestDlg::OnBnClickedBtSend()
{// TODO: Add your control notification handler code hereUpdateData(TRUE);if(m_ClientSocket.m_bConnected){//将用户输入的数据从CString转化为char *字符串,即Unicode-->ANSI,并保存到m_ClientSocket.m_szBuffer中int len =WideCharToMultiByte(CP_ACP,0,m_MsgS,-1,NULL,0,NULL,NULL);WideCharToMultiByte(CP_ACP,0,m_MsgS,-1,m_ClientSocket.m_szBuffer,len,NULL,NULL );m_ClientSocket.m_nLength =strlen(m_ClientSocket.m_szBuffer);m_ClientSocket.AsyncSelect(FD_WRITE);//触发写事件m_MsgS =_T("");UpdateData(FALSE);}
}void CSocketTestDlg::OnBnClickedBtClose()
{// TODO: Add your control notification handler code herem_ClientSocket.ShutDown();EndDialog(0);
}

OK,完!

使用CAsyncSocket类进行网络编程相关推荐

  1. Java程序设计——URLDecoder类和URLEncoder类(网络编程)

    普通字符串和MIME字符串之间的转换工具:URLDecoder和URLEncoder工具类 URLDecoder工具类: 方法 功能 decode(String s, String enc) 将MIM ...

  2. python网络编程视频教程_Java网络开发视频教程 – 一站式学习Java网络编程视频教程 全面理解BIO(无密)...

    Java网络开发视频教程 – 一站式学习Java网络编程视频教程 全面理解BIO(无密) 全面理解BIO/NIO/AIO 网络层编程,是每一个开发者都要面对的技术.课程为解决大家学习网络层知识的难题, ...

  3. 网络编程 正则表达式

    Day24-网络编程&正则表达式 网络编程 1.1 概述 Java是 Internet 上的语言,它从语言级上提供了对网络应用程 序的支持,程序员能够很容易开发常见的网络应用程序. Java提 ...

  4. Java基础:18. 网络编程

    目录 1 网络编程的常识​​​​​​ 1.1 七层网络模型 1.2 相关的协议 1.3 IP地址 1.4 端口号 2 基于tcp协议的编程模型 2.1 C/S架构的简介 2.2 编程模型 2.3 相关 ...

  5. java 网络编程详细解析

    文章目录 java 网络编程详细解析 网络编程的常识 七层网络模型 相关的协议(笔试题) 协议的概念 TCP协议 UDP协议 IP地址(重点) 查看IP地址的方式: 特殊的地址 端口号(重点) 基于t ...

  6. C#网络编程——网络应用编程

    文章目录 网络编程--第一章 1.1 网络应用编程模型 1.2 TCP/IP网络协议 1.3 传统的网络编程技术 1. 套接字编程^(socket)^(作用在网络层和传输层之间的) 2. TCP应用编 ...

  7. 【Android 应用开发】Android 网络编程 API笔记 - java.net 包 权限 地址 套接字 相关类 简介

    Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...

  8. C# 网络编程之使用Socket类Send、Receive方法的同步通讯

    经过几天学习,终于解决了再C#网络编程中使用Socket类Send和Receive方法开发的客户端和服务端的同步通讯程序:实现了又客户端想服务器发送消息的界面程序.主要使用的方法是:       1. ...

  9. Java 网络编程(二) 两类传输协议:TCP UDP

    两类传输协议:TCP,UDP TCP TCP是Transfer Control Protocol(传输控制协议)的简称,是一种面向连接的保证可靠传输的协议. 在TCP/IP协议中, IP层主要负责网络 ...

最新文章

  1. 从4个月到7天,Netflix开源Python框架Metaflow有何提升性能的魔法?
  2. 开发板通过NTS挂载在PC机中的文件夹
  3. 什么是ActiveX插件
  4. LiveVideoStack主编观察04 /
  5. 依赖Zookeeper生成全局唯一序列号
  6. spring学习(47):bean的作用域
  7. Android P功能
  8. SQL Server 2005 无法连接服务器(error:10061)
  9. 电路交换,报文交换和分组交换的原理、区别、优缺点
  10. KGB知识图谱,利用科技解决传统知识图谱问题
  11. Unity-动画机学习
  12. like查询索引失效问题与解决办法
  13. python数字转中文大写_python 数字转换为大写
  14. iOS程序员面试笔试宝典整理
  15. WIN10 Outlook 2013 pst/ost邮件数据文件迁移
  16. 2201: 逆置线性表(线性表)
  17. java 修饰符 详解,详解Java修饰符
  18. 安装oracle提示删除asm服务,卸载 ASM
  19. ChatGPT最快镜像,免费使用
  20. 爱思服务器显示磁盘空间不足,iPhone 11 有储存空间,但仍会提示“空间不足”怎么办?...

热门文章

  1. 莫烦python-Tensorflow笔记
  2. C语言获取文件的大小
  3. 想成为职场老手就用这几款办公软件
  4. WebForm登陆验证,判断用户是否登陆 PageBase类
  5. Photoshop初学者教程:解析色彩平衡原理
  6. VL170的浅应用分享
  7. html调起苹果手机摄像头_html5 file调用手机摄像头
  8. 10亿行C ++代码使用3万元/个的电脑处理器AMD Threadripper 3990X:在64核CPU处理器256GB内存电脑上编译需要多长时间?
  9. ETL常用的三种工具介绍及对比 Datastage,Informatica 和 Kettle
  10. 代码编辑器 最佳配色_最佳在线照片编辑器