高级Socket编程技术

实验目的
1.了解阻塞与非阻塞模式Socket编程的工作原理。
2.了解Socket编程的5种模型的工作原理和使用方法。
3.掌握Select模型和WSAAsyncSelect模型的网络应用程序编程。
二、实验内容
1.参考教材编写工作于非阻塞模式的多线程TCP服务器应用程序和工作于非阻塞模式客户端应用程序,并进行数据收发测试。
2.编写基于WSAAsyncSelect模型、工作于并发方式的基于对话框的TCP服务器程序和客户端程序,并进行数据收发测试。

基于WSAAsyncSelect模型的服务器程序

基于WSAAsyncSelect模型的客户端程序
要求:(1)客户端程序和服务器端程序之间都能够多次发送消息给对方,也能够多次接收对方发送的消息。(2)将上述1小题的全部代码附在附录上,将2小题源代码打包和实验报告一并提交。
三、实验原理
1.非阻塞模式
概念
Ioctlsocket
函数功能是控制套接口的模式,可用于任一状态的任一套接口,可以调用次函数来讲Socket设置为非阻塞模式。
CreateThread函数
用于创建于一个专门的通信线程,实现多客户端通信。
WSAEWOULDBLOCK
Winsock异常 WSAEWOULDBLOCK说明Output Buffer 已经满了,无法再写入数据
2. WSAAsyncSelect模型工作原理
WSAAsyncSelect模型是Windows Sockets的一个异步I/O模型。应用程序可以用它在一个套接字上接收以Windows消息为基础的网络事件。应用程序创建套接字后,调用WSAAsyncSelect()函数注册感兴趣的网络事件,当事件发生时,windows窗口接收到消息,然后程序就可以对收到的网络事件进行处理。WSAAsyncSelect模型是非阻塞的。应用程序在调用recv()函数接收数据之前,调用WSAAsyncSelect()函数注册网络事件。WSAAsyncSelect()函数立即返回,线程继续运行。当系统中数据准备好时,向应用程序发送消息。程序接收到消息后调用recv()函数接收数据。
WSAAsyncSelect函数编程方法步骤
1)初始化套接字相关信息:
(2)开始启动一个事件通知。WSAAsyncSelect(Sock,hWnd,自定义消息,网络事件)
(3)响应窗口的自定义消息处理函数,其中lparam的高位字包含了可能出现的错误
代码,低字节表示发生的网络事件。wParam表示发生网络事件的套接字。
WSAGETSELECTERROR(lParam);查看是否出现错误,获取低字节位
WSAGETSELECTEVENT(lParam);查看发生了什么事件,获取高字节位
事件种类请查看MSDN,可用WSAGetLastError()来获取错误信息。
四、实验步骤
1.非阻塞模式下的客服端和服务器端信息的收发测试,如图,客户端1在1588端口上向服务器端发送数据,客户端2在3124端口上向服务器端发送数据。处于非阻塞状态。

  1. 基于WSAAsyncSelect模型、工作于并发方式的基于对话框的TCP服务器程序和客户端程序,并进行数据收发测试。


五、实验小结
附:程序源代码
服务器(窗口)

#include "stdafx.h"
#include "Exp07_AsyncServer.h"#include<WINSOCK2.h>
#pragma comment(lib,"ws2_32.lib")#define MAX_LOADSTRING 100#define WM_SOCKET WM_USER+0x10    //①自定义socket消息// 全局变量:
HINSTANCE hInst;                                // 当前实例
TCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名SOCKET sockSer,sockConn;            //服务器端要创建两个套接字
SOCKADDR_IN addrSer, addrCli;
int len =sizeof(SOCKADDR);
char sendbuf[256],recvbuf[256];
char clibuf[999]="客户端: >",serbuf[999]="服务器: >";// 此代码模块中包含的函数的前向声明:
BOOL                InitInstance(HINSTANCE, int);
INT_PTR CALLBACK    AsyncSrvProc(HWND, UINT, WPARAM, LPARAM);int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPTSTR    lpCmdLine,_In_ int       nCmdShow)
{UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine);// TODO: 在此放置代码。MSG msg;HACCEL hAccelTable;// 初始化全局字符串LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadString(hInstance, IDC_EXP07_ASYNCSERVER, szWindowClass, MAX_LOADSTRING);// 执行应用程序初始化:if (!InitInstance (hInstance, nCmdShow)){return FALSE;}hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_EXP07_ASYNCSERVER));// 主消息循环:while (GetMessage(&msg, NULL, 0, 0)){if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)){TranslateMessage(&msg);DispatchMessage(&msg);}}return (int) msg.wParam;
}//
//   函数: InitInstance(HINSTANCE, int)
//
//   目的: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{HWND hWnd;hInst = hInstance; // 将实例句柄存储在全局变量中hWnd =CreateDialog(hInstance, MAKEINTRESOURCE(IDD_SERVER), GetDesktopWindow(), AsyncSrvProc);if (!hWnd){return FALSE;}ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);return TRUE;
}// “关于”框的消息处理程序。
INT_PTR CALLBACK AsyncSrvProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{UNREFERENCED_PARAMETER(lParam);char ip[16],port[5];    switch (message){case WM_INITDIALOG:SetDlgItemText(hDlg,IDC_IP,"127.0.0.1");  //设置ip文本框的内容SetDlgItemText(hDlg,IDC_PORT,"5566"); //设置端口文本框的内容WSADATA wsaData;if(WSAStartup(MAKEWORD(2,2), &wsaData)) {MessageBox(hDlg,"Winsock加载失败","警告",0);WSACleanup();return (INT_PTR)TRUE;}case WM_SOCKET:   //三:自定义消息    if(WSAGETSELECTERROR(lParam)){MessageBoxA(NULL, "Socket错误", "tip", 0);  }else{switch (WSAGETSELECTEVENT(lParam)) {  //选择要处理的事件case FD_ACCEPT:{   //接收请求事件               sockConn=accept(sockSer,(SOCKADDR*) &addrCli,&len);    WSAAsyncSelect(sockConn, hDlg,WM_SOCKET,FD_READ | FD_CLOSE); }break;case FD_READ:  {        //可读事件          recv(sockConn,recvbuf,256,0);   //接收消息strcat_s(clibuf,recvbuf);//将接收到的消息添加到列表框中SendDlgItemMessage(hDlg,IDC_RECVBUF,LB_ADDSTRING,0,(LPARAM)clibuf);strcpy_s(clibuf, "客户端: >"); }    //重新给字符串赋值          break;          case FD_CLOSE:  { //关闭连接事件          MessageBoxA(NULL, "正常关闭连接", "tip", 0);  }                   break;      }//switch (WSAGETSELECTEVENT(lParam)) }//elsebreak;case WM_COMMAND:switch(LOWORD(wParam) ){ case IDC_QUIT:  //单击了退出按钮EndDialog(hDlg, LOWORD(wParam));closesocket(sockSer);  //关闭套接字 WSACleanup();       //卸载WinSock协议栈return TRUE;          case IDC_CREATE:        //单击了创建服务器按钮GetDlgItemText(hDlg,IDC_IP,ip,16);  //获取编辑框中的IP值GetDlgItemText(hDlg,IDC_PORT,port,5);EnableWindow(GetDlgItem(hDlg,IDC_CREATE),FALSE); //禁用按钮sockSer=socket(AF_INET,SOCK_STREAM,0);//②设置异步方式WSAAsyncSelect(sockSer, hDlg,WM_SOCKET,FD_ACCEPT); addrSer.sin_family=AF_INET;addrSer.sin_port=htons(atoi(port));addrSer.sin_addr.S_un.S_addr=inet_addr(ip);bind(sockSer,(SOCKADDR*) &addrSer,len);  //绑定套接字listen(sockSer,5);           //监听                break;case IDC_SEND:                //单击了发送按钮GetDlgItemText(hDlg,IDC_SENDBUF,sendbuf,256);send(sockConn,sendbuf,strlen(sendbuf)+1,0);  //发送消息SetDlgItemText(hDlg,IDC_SENDBUF,NULL);        //清空编辑框strcat_s(serbuf,sendbuf);//将已发送的消息添加到列表框中SendDlgItemMessage(hDlg,IDC_RECVBUF,LB_ADDSTRING,0,(LPARAM)serbuf);strcpy_s(serbuf, "服务器: >");break;               }   //switch(LOWORD(wParam) )   }//switch (message) return (INT_PTR)FALSE;
}

客户端(窗口)

#include "stdafx.h"
#include "Exp07_AsyncClient.h"#include<WINSOCK2.h>
#pragma comment(lib,"ws2_32.lib")#define WM_SOCKET WM_USER+0x10    //①自定义socket消息#define MAX_LOADSTRING 100// 全局变量:
HINSTANCE hInst;                                // 当前实例
TCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名SOCKET sockCli;         //声明客户端套接字
SOCKADDR_IN addrSer;// 此代码模块中包含的函数的前向声明:
BOOL                InitInstance(HINSTANCE, int);
INT_PTR CALLBACK    AsyncClientProc(HWND, UINT, WPARAM, LPARAM);int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPTSTR    lpCmdLine,_In_ int       nCmdShow)
{UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine);// TODO: 在此放置代码。MSG msg;HACCEL hAccelTable;// 初始化全局字符串LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadString(hInstance, IDC_EXP07_ASYNCCLIENT, szWindowClass, MAX_LOADSTRING);   // 执行应用程序初始化:if (!InitInstance (hInstance, nCmdShow)){return FALSE;}hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_EXP07_ASYNCCLIENT));// 主消息循环:while (GetMessage(&msg, NULL, 0, 0)){if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)){TranslateMessage(&msg);DispatchMessage(&msg);}}return (int) msg.wParam;
}//
//   函数: InitInstance(HINSTANCE, int)
//
//   目的: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{HWND hWnd;hInst = hInstance; // 将实例句柄存储在全局变量中hWnd =CreateDialog(hInstance, MAKEINTRESOURCE(IDD_ASYNCCLIENT), GetDesktopWindow(), AsyncClientProc);if (!hWnd){return FALSE;}ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);return TRUE;
}// “关于”框的消息处理程序。
INT_PTR CALLBACK AsyncClientProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{UNREFERENCED_PARAMETER(lParam);char ip[16], port[5];char sendbuf[256],recvbuf[256],ren[10];    char serbuf[256]="服务器: >", clibuf[256]="客户端: >";int len =sizeof(SOCKADDR);int res;switch (message){case WM_INITDIALOG:                 //对话框初始化SetDlgItemText(hDlg,IDC_IP,"127.0.0.1");SetDlgItemText(hDlg,IDC_PORT,"5566");WSADATA wsaData;WSAStartup(MAKEWORD(2,2), &wsaData);       //加载协议栈sockCli=socket(AF_INET,SOCK_STREAM,0);      //创建套接字//设置异步方式WSAAsyncSelect(sockCli, hDlg,WM_SOCKET, FD_READ |FD_CLOSE);  break;case WM_SOCKET:   //自定义消息     switch (WSAGETSELECTEVENT(lParam)){case FD_READ: {   //可读事件         recv(sockCli,recvbuf,256,0);        //接收信息strcat_s(serbuf,recvbuf);//将接收到的数据添加到列表框中SendDlgItemMessage(hDlg,IDC_RECVBUF,LB_ADDSTRING,0,(LPARAM)serbuf);strcpy_s(serbuf, "服务器: >");  }   //重新给字符串赋值          break;          case FD_CLOSE: {             //关闭连接事件           MessageBoxA(NULL, "正常关闭连接", "tip", 0);      }break;     }       break;      case WM_COMMAND:{   switch(LOWORD(wParam))  { case IDC_QUIT:                    //单击了退出按钮EndDialog(hDlg, LOWORD(wParam));closesocket(sockCli);WSACleanup();break;       case IDC_CONN:                  //单击了“连接服务器”按钮GetDlgItemText(hDlg,IDC_IP,ip,16);        //获取ipGetDlgItemText(hDlg,IDC_PORT,port,5);EnableWindow(GetDlgItem(hDlg,IDC_CONN),FALSE);   //禁用连接按钮addrSer.sin_family=AF_INET;addrSer.sin_port=htons(atoi(port));addrSer.sin_addr.S_un.S_addr=inet_addr(ip);        res =connect(sockCli,(SOCKADDR*)&addrSer,sizeof(SOCKADDR));//   itoa(res,ren,10);// MessageBox(NULL,ren,"通知",0); if(res ==10035 || res==-1)MessageBox(NULL,"客户端连接服务器成功","通知",0);             else    MessageBox(NULL,"客户端连接服务器失败","警告",0);       break;case IDC_SEND:        //单击了“发送”按钮GetDlgItemText(hDlg,IDC_SENDBUF,sendbuf,256);        //获得发送框的内容send(sockCli,sendbuf,strlen(sendbuf)+1,0);       //发送消息SetDlgItemText(hDlg,IDC_SENDBUF,"");        //清空发送框strcat_s(clibuf,sendbuf);                SendDlgItemMessage(hDlg,IDC_RECVBUF,LB_ADDSTRING,0,(LPARAM)clibuf);strcpy_s(clibuf, "客户端: >");  //重新给字符串赋值 break;}//switch(LOWORD(wParam))}//case WM_COMMAND:}return (INT_PTR)FALSE;
}
服务器://
#include <afxwin.h>#include "stdafx.h"
#include <WINSOCK2.H>
#include <iostream>#pragma comment(lib,"WS2_32.lib")
#define BUF_SIZE    64      // 缓冲区大小sockaddr_in addrClient;                         // 客户端地址DWORD  WINAPI  AnswerThread(LPVOID  lparam)
{  char   buf[BUF_SIZE];            // 用于接受客户端数据的缓冲区   int     retVal;                          // 调用各种Socket函数的返回值   SOCKET  sClient=(SOCKET)(LPVOID)lparam;  // 循环接收客户端的数据,直接客户端发送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(sClient);   WSACleanup();   return -1;   }}   // 获取当前系统时间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); while(true){// 向服务器发送数据retVal = send(sClient, msg, strlen(msg),0);   if(SOCKET_ERROR == retVal)   {   int err = WSAGetLastError();if(err == WSAEWOULDBLOCK)            // 无法立即完成非阻塞套接字上的操作{Sleep(500);continue;}else{printf("send failed !\n");   closesocket(sClient);   WSACleanup();   return -1;   }}break;}   }}// 关闭套接字closesocket(sClient);
}int _tmain(int argc, _TCHAR* argv[])
{WSADATA wsd;                   // WSADATA变量,用于初始化Windows Socket   SOCKET  sServer;                  // 服务器套接字,用于监听客户端请求SOCKET  sClient;                  // 客户端套接字,用于实现与客户端的通信   int     retVal;                          // 调用各种Socket函数的返回值   // 初始化套接字动态库   if(WSAStartup(MAKEWORD(2,2),&wsd) != 0)   {   printf("WSAStartup failed !\n");   return 1;   }     // 创建用于监听的套接字   sServer = socket(AF_INET,SOCK_STREAM, IPPROTO_IP);   if(INVALID_SOCKET == sServer)   {   printf("socket failed !\n");   WSACleanup();   return -1;   }     // 设置套接字为非阻塞模式int iMode = 1;retVal = ioctlsocket(sServer, FIONBIO, (u_long FAR*) &iMode);if(retVal == SOCKET_ERROR){printf("ioctlsocket failed !\n");WSACleanup();return -1;}// 设置服务器套接字地址   SOCKADDR_IN addrServ;   addrServ.sin_family = AF_INET;   addrServ.sin_port = htons(9990);       // 监听端口为9990addrServ.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, SOMAXCONN);   if(SOCKET_ERROR == retVal)   {   printf("listen failed !\n");   closesocket(sServer);   WSACleanup();   return -1;   }     // 接受客户请求   printf("TCP Server start...\n");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;   //   Sleep(100);//   continue;//}} // 创建专用通信线程DWORD dwThreadId;CreateThread(NULL, NULL, AnswerThread, (LPVOID)sClient, 0, &dwThreadId);}// 释放套接字   closesocket(sServer);   WSACleanup();   // 暂停,按任意键退出system("pause");return 0;
}客户端:
#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 Socketif(WSAStartup(MAKEWORD(2,2),&wsd) != 0)   {   printf("WSAStartup failed !\n");   return 1;   }     // 创建套接字   sHost = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);   if(INVALID_SOCKET == sHost)   {   printf("socket failed !\n");   WSACleanup();   return -1;   }// 设置套接字为非阻塞模式int iMode = 1;retVal = ioctlsocket(sHost, FIONBIO, (u_long FAR*) &iMode);if(retVal == SOCKET_ERROR){printf("ioctlsocket 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);                                int sServerAddlen = sizeof(servAddr);                                              // 计算地址的长度       // 循环等待while(true){// 连接服务器   Sleep( 200 );retVal = connect(sHost,(LPSOCKADDR)&servAddr,sizeof(servAddr));   Sleep( 200 );if(SOCKET_ERROR == retVal)   {   int err = WSAGetLastError();if(err == WSAEWOULDBLOCK || err == WSAEINVAL)           // 无法立即完成非阻塞套接字上的操作{//Sleep(500);continue;}else if(err == WSAEISCONN)                                             // 已建立连接{break;}else{//continue;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);          // 接收输入的数据ZeroMemory(buf,BUF_SIZE);   strcpy(buf,str.c_str());              // 将用户输入的数据复制到buf中 while(true){// 向服务器发送数据retVal = send(sHost,buf,strlen(buf),0);   if(SOCKET_ERROR == retVal)   {   int err = WSAGetLastError();if(err == WSAEWOULDBLOCK)          // 无法立即完成非阻塞套接字上的操作{Sleep(500);continue;}else{printf("send failed !\n");   closesocket(sHost);   WSACleanup();   return -1;   }}break;}     int count=0;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);count=count+1;if (count<10){printf("waiting back msg !\n");continue;} else{printf("recv back msg failed! \n");break;}}else if(err == WSAETIMEDOUT || err == WSAENETDOWN){printf("recv failed !\n");   closesocket(sHost);   WSACleanup();   return -1;}break;}   break;}   //ZeroMemory(buf,BUF_SIZE);                     // 清空接收数据的缓冲区//retVal = recv(sHost,buf,sizeof(buf)+1,0);     // 接收服务器回传的数据   printf("Recv From Server: %s\n\n",buf);   if(strcmp(buf, "quit") == 0)          // 如果收到quit,则退出{printf("quit!\n");break;}}closesocket(sHost);   WSACleanup();  system("pause");return 0;
}

高级Socket编程技术相关推荐

  1. TCP:利用Socket编程技术实现客户端向服务端上传一个图片。

    问题: 利用Socket编程技术实现客户端向服务端上传一个图片的程序. 客户端: import java.io.*; import java.net.Socket;public class clien ...

  2. JAVA之Socket编程(技术总结)

    1.socket编程实例1--Socket客户端(字符串)->请求到Socket服务端->响应客户端: 代码如下: import java.io.BufferedReader; impor ...

  3. Socket 编程实现基于 HTTP 协议的客户和服务

    目录 前言 研究背景及意义 研究内容及方法 研究要求与目标 相关知识点 HTTP协议 TCP协议 UDP协议 Socket编程技术 需求分析 Socket编程 Swing包 多线程的应用 功能设计 功 ...

  4. Socket编程--自己动手的HTTP代理服务器

    浏览器使用代理:Firefox浏览器: 选项->高级->连接->设置,选择手动配置代理. 实现http代理: 1.等待来自一个客户端的连接: 2.启动一个新线程来处理连接: Inpu ...

  5. JNI_编程技术__网文整理

    Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... 11 Chap 3:javah命令帮助信息... 16 Chap 4:用javah产生一个.h文件... 17 Chap5:j ...

  6. Unix网络编程(六)高级I/O技术之复用技术 select

    转载:http://blog.csdn.net/michael_kong_nju/article/details/44887411 I/O复用技术 本文将讨论网络编程中的高级I/O复用技术,将从下面几 ...

  7. 鼠标绘图 c语言,c语言高级编程技术教程 图形显示方式与鼠标输入.doc

    c语言高级编程技术教程 图形显示方式与鼠标输入 c语言高级编程技术教程 图形显示方式和鼠标输入 图形显示方式和鼠标输入 问题的提出编写程序,使用鼠标进行如下操作:按住鼠标器的任意键并移动,十字光 标将 ...

  8. 基于socket网络编程技术实现TCP和UDP的流程详解及实例

    具体函数讲解太多,根据程序自行分析. 可以参考这篇文章: https://blog.csdn.net/qq_41687938/article/details/119102328?spm=1001.20 ...

  9. ole2高级编程技术 pdf_21天快速掌握Python语言,《21天学通Python》PDF版送给你去学...

    Python的学习书籍小编看过很多,但是这本<21天学通Python>真的是堪称极品! 本书的作者团队成员为一线开发工程师.资深编程专家或专业培训师,在编程开发方面有着丰富的经验,并已出版 ...

最新文章

  1. 软件测试--利用组合覆盖法设计测试用例
  2. tf.Session().as_default的作用
  3. ES6 Fetch API和Cookie相关的知识点
  4. Winodws live writer
  5. 雅虎、领英接连退出中国,GitHub 会受到影响吗?
  6. 搭建Magento电子商务网站
  7. html动态资源加载进度,JavaScript_快速解决js动态改变dom元素属性后页面及时渲染的问题,今天实现一个进度条加载过程 - phpStudy...
  8. ajax 页面部分先显示图片后出数据
  9. SPOJ QTREE4 lct
  10. 文字和表单(checkbox/radio)元素垂直对齐方法,兼容Firefox和IE。
  11. 软件測试自学指南---从入门到精通
  12. 大学排行榜 : qs全球世界 大学排行榜
  13. Maya2018安装报错(错误代码1612)
  14. word之中快速插入已有公式的几种方法
  15. 电脑电源问题,导致攒机电脑无法开机
  16. java高德地图api开发平台_【高德地图API】从零开始学高德JS API(一)地图展现...
  17. 3D数学基础及坐标系统
  18. 片段中onCreate(),onCreateView()和onActivityCreated()的区别和用法
  19. 计算机连接网络被限制,wifi连接被限制怎么办,教您wifi显示网络受限如何解决
  20. 人的一生,到底在追求甚麼

热门文章

  1. 苹果手机不小心删除的短信怎么恢复?
  2. pg limit限制返回的行
  3. java怎么调字体_java里面怎样设置字体大小?
  4. day01---day06
  5. 微信公众号如何获取手机号,H5调用小程序,小程序调用H5
  6. 在 DAZ STUDIO 中创建水面
  7. 关于git和gitee下载使用以及在idea中使用的情况
  8. 查看远程端口开放状态
  9. 计算机主键盘,电脑的主键盘中都有哪些键组成
  10. 【冷链物流】2016年冷链物流行业研究报告