爱站内页反链 爱站首页反链 神马是否收录 360网站安全检测 搜狗是否收录 360是否收录 百度是否收录 百度年收录 网站年龄 百度安全 百度查询 导出链接 网站ip查询 网站ICP备案批量查询 搜狗快照 百度快照 百度反链批量查询 搜狗PR批量查询 谷歌PR批量查询 神马权重批量查询 360移动权重批量查询 站长移动权重批量查询 爱站移动权重批量查询 360权重查询 站长PC权重批量查询 爱站PC权重批量查询 搜狗总收录批量查询 360日收录批量查询 360总收录批量查询 百度月收录批量查询 百度周收录批量查询 百度日收录批量查询 百度网站收录批量查询 获取网站IP 获取网站描述 获取网站关键词 获取网站标题 HTTP状态码 搜狗权重 搜狗反链 神马总收录 百度预计流量 ALEXA排名 360反链

当前位置 博文首页 > nandejxy的博客:C++ socket编程 实现服务端与客户端的双向TCP通

最大化 缩小

    nandejxy的博客:C++ socket编程 实现服务端与客户端的双向TCP通

    作者:[db:作者] 时间:2021-07-26 21:01

    运行环境:VS2015

    基于https://blog.csdn.net/orange_xxx/article/details/7276868做出了简单修改,可以完全实现双向的数据通信;

    TCP通信流程

    【来自https://blog.csdn.net/u012801153/article/details/79363575】

    Server步骤:

    1. 加载套接字库,创建套接字(WSAStartup()/socket());
    2. 绑定套接字到一个IP地址和一个端口上(bind());
    3. 将套接字设置为监听模式等待连接请求(listen());
    4. 请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept());
    5. 用返回的套接字和客户端进行通信,接收来自client的信息(recv()),发送回复信息至client(send());
    6. 返回,等待另一连接请求;
    7. 关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。

    Client步骤:

    1. 加载套接字库,创建套接字(WSAStartup()/socket());
    2. 绑定套接字到一个IP地址和一个端口上(bind());
    3. 向服务器发出连接请求(connect());
    4. 和服务器端进行通信,发送请求信息至server(send());接收server的回复信息(recv());
    5. 关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。

    github代码:https://github.com/jiangxinyiba/NetworkCommu_demo/tree/master

    服务端代码Server.cpp:

    #include "winsock2.h"
    #include <WS2tcpip.h>
    #include <iostream>
     
    #pragma comment(lib, "ws2_32.lib") // load the dll of winsock
    using namespace std;
    
    int main(int argc, char* argv[])
    {
    	const int BUF_SIZE = 64;
    	WSADATA			wsd;			    //WSADATA PARAM
    	SOCKET			sServer;		    //Server Socket
    	SOCKET			sClient;		    //Client Socket
    	SOCKADDR_IN		servAddr;		    //Server Addr
    	SOCKADDR_IN     clientAddr;         //Client Addr
    	SOCKADDR_IN     connect_Addr;       //the Addr that connect this socket (in this demo, connect_Addr = clientAddr)
    	int             connectClientlen = sizeof(connect_Addr);
    	char			bufSend[BUF_SIZE];	//the buffer area of data-send
    	char			bufRecv[BUF_SIZE];  //the buffer area of data-recv
    	int				retVal;			    //return value
    	char*			closeSymbol = "0";  //symbol of closing communication
    	char*           bufReq = "Request Reply";  // symbol of Request Reply
    	char            str[INET_ADDRSTRLEN];
    
        // Server Addr
    	servAddr.sin_family = AF_INET;
    	inet_pton(AF_INET, "127.0.0.1", (void*)&servAddr.sin_addr.S_un.S_addr);
    	servAddr.sin_port = htons((short)5000);
    
    	// Client Addr
    	clientAddr.sin_family = AF_INET;
    	inet_pton(AF_INET, "127.0.0.1", (void*)&clientAddr.sin_addr.S_un.S_addr);
    	clientAddr.sin_port = htons((short)4999);
    
    	// Initialize the dll of winsock
    	if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
    	{
    		cout << "WSAStartup failed !" << endl;
    		return 1;
    	}
    
    	// Create the Server socket 
    	sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    	if (INVALID_SOCKET == sServer)
    	{
    		cout << "socket failed!" << endl;
    		WSACleanup();			 
    		return  -1;
    	}
    	else
    	{
    		cout << "Server TCP Socket init!" << endl;
    	}
    
    	// Bind the IP and Port on Server Socket 
    	retVal = bind(sServer, (LPSOCKADDR)&servAddr, sizeof(SOCKADDR_IN));
    	if (SOCKET_ERROR == retVal)
    	{
    		cout << "bind failed!" << endl;
    		closesocket(sServer);
    		WSACleanup();
    		Sleep(5000);
    		return -1;
    	}
    	else
    	{
    		cout << "Server TCP Socket bind IP & Port !" << endl;
    		cout << "Server Address = " << inet_ntop(AF_INET, &servAddr.sin_addr, str, sizeof(str)) << ":" << ntohs(servAddr.sin_port) << endl;
    	}
    
    	// Listen the Server socket 
    	retVal = listen(sServer, 10);
    	if (0 == retVal)
    	{
    		cout << "Server Socket is listening !" << endl;
    	}
    	else if (SOCKET_ERROR == retVal)
    	{
    		cout << "listen failed!" << endl;
    		closesocket(sServer);	 
    		WSACleanup();	
    		Sleep(5000);
    		return -1;
    	}
    
    	cout << "Server Socket is waiting accpetion !" << endl;
    	sClient = accept(sServer, (sockaddr FAR*)&connect_Addr, &connectClientlen);
    	if (INVALID_SOCKET == sClient)
    	{
    		cout << "accept failed!" << endl;
    		closesocket(sServer);	
    		WSACleanup();
    		Sleep(5000);
    		return -1;
    	}
    	else
    	{
    		cout << "Server get connection with client socket: [" << inet_ntop(AF_INET, &connect_Addr.sin_addr, str, sizeof(str)) << ":" << ntohs(connect_Addr.sin_port) << "]" << endl;
    	}
    
    	// loop for the data from the accpeted socket/send the data to the socket 
    	while (TRUE) 
    	{
    		// Initialize the buffer 
    		ZeroMemory(bufRecv, BUF_SIZE);
    
    		// Recevice the buffer data from the client 
    		retVal = recv(sClient, bufRecv, BUF_SIZE, 0);
    		if (SOCKET_ERROR == retVal)
    		{
    			continue;
    		}
    
    		// Check the data from client 
    		bufRecv[retVal] = '\0';			// Set the last bit as \0 to avoid the wrong data  
    		cout << "Data recv from Client Socket [" << inet_ntop(AF_INET, &connect_Addr.sin_addr, str, sizeof(str)) << ":" << ntohs(connect_Addr.sin_port) << "] : " << bufRecv << endl;
    		// When the data from client is ‘0’,exit the loop and finish TCP Communication
    		if (!strcmp(bufRecv, closeSymbol))
    		{
    			cout << "Client Socket wants to finish this communication" << endl;
    			closesocket(sServer);
    			WSACleanup();
    			Sleep(5000);
    			break;
    		}
    		else
    		{
    			// Automatically send the request reply to client  
    			send(sClient, bufReq, strlen(bufReq), 0);
    		}
    	}
    	// Exit
    	closesocket(sServer);	 
    	WSACleanup();			 
    	Sleep(5000);
    	return 0;
    }

    客户端代码Client.cpp:

    // Client.cpp : Defines the entry point for the console application.
    #include "winsock2.h"
    #include <WS2tcpip.h>
    #include <iostream>
    #pragma comment(lib, "ws2_32.lib")
    
    #define _WINSOCK_DEPRECATED_NO_WARNINGS
    
    using namespace std;
    
    int main(int argc, char* argv[])
    {
    	const int BUF_SIZE = 64;
    	WSADATA			wsd;			    //WSADATA Param
    	SOCKET			sClient;		    //Server Socket 
    	SOCKADDR_IN		servAddr;		    //Server Addr 
    	SOCKADDR_IN     clientAddr;         //Client Addr
    	SOCKADDR_IN     send_Data_Addr;     //the Addr that send the data(in this demo, send_Data_Addr = servAddr)
    	int				nAddrLen = sizeof(clientAddr);
    	int				nAddrLen_s = sizeof(servAddr);
    	char			bufSend[BUF_SIZE];	//the buffer area of data-send
    	char			bufRecv[BUF_SIZE];  //the buffer area of data-recv
    	int				retVal;			    //return value
    	char*			closeSymbol = "0";  //symbol of close
    
        // Server Addr
    	servAddr.sin_family = AF_INET;
    	inet_pton(AF_INET, "127.0.0.1", (void*)&servAddr.sin_addr.S_un.S_addr);
    	servAddr.sin_port = htons((short)5000);
    	int	nServAddlen = sizeof(servAddr);
    
    	// Client Addr
    	clientAddr.sin_family = AF_INET;
    	inet_pton(AF_INET, "127.0.0.1", (void*)&clientAddr.sin_addr.S_un.S_addr);
    	clientAddr.sin_port = htons((short)4999);
    	int	nClientAddlen = sizeof(clientAddr);
    
    	// Initialize the dll of winsock
    	if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
    	{
    		cout << "WSAStartup failed!" << endl;
    		return -1;
    	}
    
    	// Create the Server socket 
    	sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    	if (INVALID_SOCKET == sClient)
    	{
    		cout << "Socket failed !" << endl;
    		WSACleanup();       
    		Sleep(5000);
    		return  -1;
    	}
    	else
    	{
    		cout << "Client Socket init !" << endl;
    	}
    
    	// Bind the client socket with IP and Port 
    	retVal = bind(sClient, (LPSOCKADDR)&clientAddr, sizeof(SOCKADDR_IN));
    	if (SOCKET_ERROR == retVal)
    	{
    		cout << "bind failed!" << endl;
    		closesocket(sClient);
    		WSACleanup();
    		Sleep(5000);
    		return -1;
    	}
    	else
    	{
    		cout << "Client UDP Socket bind IP & Port !" << endl;
    		char str[INET_ADDRSTRLEN];
    		cout << "Client Address = " << inet_ntop(AF_INET, &clientAddr.sin_addr, str, sizeof(str)) << ":" << ntohs(clientAddr.sin_port) << endl;
    	}
    
    	// client request connect server socket
    	retVal = connect(sClient, (LPSOCKADDR)&servAddr, sizeof(servAddr));
    	if (SOCKET_ERROR == retVal)
    	{
    		cout << "Client connect failed!" << endl;
    		closesocket(sClient);	 
    		WSACleanup();	
    		Sleep(5000);
    		return -1;
    	}
    	else
    	{
    		cout << "Client connect with Server socket" << endl;
    	}
    
    	// loop for the data from the connected socket/send the data to the server socket 
    	while (true) {
    		// Initialize the buffer
    		ZeroMemory(bufSend, BUF_SIZE);
    
    		// Send the data from client socket to Server Socket
    		cout << "Data send to Server Socket: ";
    		cin >> bufSend;
    		retVal = send(sClient, bufSend, strlen(bufSend), 0);
    		if (SOCKET_ERROR == retVal)
    		{
    			cout << "Send failed!" << endl;
    			closesocket(sClient);	 
    			WSACleanup();	
    			Sleep(5000);
    			return -1;
    		}
    		// When the data from another socket is ‘0’,exit the loop and finish TCP Communication	
    		if (!strcmp(bufSend, closeSymbol))
    		{
    			cout << "Client Socket wants to finish this communication" << endl;
    			break;
    		}
    
    		// Receive data from server socket
    		retVal = recv(sClient, bufRecv, BUF_SIZE, 0);
    		bufRecv[retVal] = '\0';
    		cout << "Data recv from Server Socket: " << bufRecv << endl;
    	}
    
    	closesocket(sClient);	 
    	WSACleanup();		
    
    	Sleep(5000);
    	return 0;
    }

    ?


    注意事项

    1. inet_pton(AF_INET, "127.0.0.1", (void*)&servAddr.sin_addr.S_un.S_addr);这句话是替代了inet_addr的作用,vs2015里面inet_addr好像不能用了,只能用inet_pton替代,之前需要添加#include <WS2tcpip.h>。这里是单机内两个进程间的通信,最后采用的是127.0.0.1的localhost作为IP地址。

    2. WSAStartup(MAKEWORD(2,2),&wsaData):其中MAKEWORD(2,2)表示使用WINSOCK2版本,wsaData用来存储系统传回的关于WINSOCK的资料;

    3. ZeroMemory(bufSend, BUF_SIZE);? ?//端口发送数据,需要在每次交互前,把之前的buf数据清空,避免缓冲区冗余;但是不能对这个端口的接受数据的缓冲bufRecv清空;这样会造成永久性的空接受情况。

    4. retVal = recv(sClient, bufRecv,BUF_SIZE , 0);? ?//端口接受另一个端口数据,字符位要选择允许的满字符,这里为BUF_SIZE,确保每次都能把另一个端口的数据全都接收到;其中retVal记录了这组数据的长度;

    5. 这里需要注意,不论是客户端还是服务端,recv和send的第一个参数都是sClient,即客户端的socket,即在TCP通信中recv和send函数的第一个参数应该是发起connect连接的socket。

    6. bufRecv[retVal] = '\0';? //每次接受到的数据因为没有初始化,初始结构都是“烫烫烫烫”,在接受到后,会把前面的若干位变成接受的数据,但是后面还是都为烫,因此需要这个语句将接受数据的缓冲收尾,接受有效的前面若干位数据,剔除烫烫烫烫。

    7. 最后通过输入0来结束本次通信,若客户端发送了一个"0",那就表示需要结束本次通信,两个进程会在5秒内自动关闭。

    8. 两个代码分别放于两个项目中,先运行启动服务端代码,然后运行客户端代码,就可以进行本机的两端通信调试。若先启动了客户端,由于代码保护,一旦客户端无法找到可以连接的服务端,客户端会马上关闭;而先打开服务端的话,服务端会一直处于等待连接状态。

    cs
    上一篇: 的博客:Qt JSON数据解析和存储详解
    下一篇:没有了
  • 立即下载 - IIS7 站长工具包
    最新 更多<<
  • nandejxy的博客:C++ socket编程 实现服务端与客户端的双向TCP通
  • 的博客:Qt JSON数据解析和存储详解
  • 漫步繁华街的专栏:QT JSON 字符串操作(解析与写入)
  • 好儿郎~志在四方:Qt:QJson操作json文件(QJsonDocument、QJsonA
  • C#:QT使用QJson生成解析,简单的JSON,复杂的Json使用方法
  • 豫:QT中Json对象,字符串 QString,字符数组 QByteArray之间的
  • Qt QJson解析json数据_张小生blingbling的博客:json qt 解析数
  • yzlworld的专栏:QT实现Json数组的Post发送
  • 若梦的博客:使用Qt读写JSON文件(一)——简单的写入文件
  • weixin_34104341的博客:Qt之JSON生成与解析
  • hk的博客:CEF3嵌入Win32 工程(2171)
  • lzh_2_4的博客:各种笔记
  • 老猿Python:《原力计划文章》专栏目录
  • 老猿Python:《老猿Python精品文章》专栏文章目录
  • 老猿Python:图像处理空间域、变换域、时域和频域的含义理解:sp
  • 龚厂长的博客:Seata解析-DefaultCoordinator的四大定时线程池功
  • 龚厂长的博客:Seata解析-TC端file.conf文件各配置作用总结
  • 龚厂长的博客:Seata解析-数据源代理DataSourceProxy详解
  • 龚厂长的博客:Seata解析-详解RM及TM的初始化过程
  • 龚厂长的博客:Seata解析-RM执行SQL语句原理详解
  • 龚厂长的博客:Seata解析-saga模式介绍
  • 龚厂长的博客:Seata解析-TM、RM如何与TC集群通讯
  • 龚厂长的博客:Mybatis解析-使用mybatis查询原理解析
  • 龚厂长的博客:Mybatis解析-缓存原理解析
  • 龚厂长的博客:Mybatis解析-执行器Executor详解
  • 龚厂长的博客:Mybatis解析-如何编写插件
  • 龚厂长的博客:Mybatis解析-自动注解MybatisAutoConfiguration详
  • 龚厂长的博客:spring boot配置文件application.properties加载
  • 龚厂长的博客:java8解惑之字符串常量池(实现原理、垃圾回收)
  • 龚厂长的博客:RocketMQ-生产者启动并发送普通消息流程详解
    推荐 更多<<
  • Python解析网页源代码中的115网盘链接实例
  • zcy_wxy的博客:Logstash报错:Logstash could not be started b
  • 怎么获取免费的win10 21H1太阳谷版激活密钥 附激活工具

深圳SEO优化公司沙井seo优化南山关键词按天计费丹竹头关键词按天收费木棉湾百姓网标王民治百度关键词包年推广横岗设计公司网站民治网站优化排名双龙网站排名优化平湖百度竞价包年推广横岗外贸网站建设坪地百姓网标王推广光明百度seo平湖网站推广工具吉祥阿里店铺托管坪山阿里店铺托管深圳网络营销吉祥网站搜索优化木棉湾百度标王沙井百度标王坪地品牌网站设计坑梓网站推广方案布吉网站改版深圳百姓网标王推广福永网站优化按天收费布吉百度标王平湖百姓网标王推广福田百姓网标王吉祥网站推广工具南联百度竞价福永设计网站歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化