C++ TCP通信

TCP协议:

        服务器 Server                                                客户端 Client

1.     确定协议版本                                           1.     确定协议版本

2.      创建socket                                              2.      创建socket

3.      确定协议地址簇                                       3.      获取服务器地址

4.      绑定                                                    

5.     监听

6.     接受客户端连接                                        4.     连接服务器

7.     通信                                                          5.     通信

8.    关闭socket                                                 6.    关闭socket

9.    清理协议版本信息                                      7.    清理协议版本信息       

用vs2019写的

单个服务器,单个客户端

Server.cpp

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<WinSock2.h>
#include<WS2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
#include<Windows.h>
#include<stdio.h>
#include<string>

int main()
{
	// 1. 确定协议版本
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		printf("请求的版本不是2.2版本!\n");
		WSACleanup();
		return -1;
	}
	printf("请求的版本为2.2版本!\n");


	// 2  创建socket
	SOCKET sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);   //结构体
	if (SOCKET_ERROR == sSocket)
	{
		printf("创建socke失败 :%d\n",GetLastError());
		return -2;
	}
	printf("创建socke成功!\n");


	// 3 确定服务器的协议地址簇
	std::string ip = "127.0.0.1";
	int port = 8080;
	SOCKADDR_IN addr = {0};
	addr.sin_family = AF_INET; // 和socket函数第一个参数保持一致
	addr.sin_addr.S_un.S_addr = inet_addr(ip.c_str()); // 
	addr.sin_port = htons(port);  // 


	// 4  绑定
	int r = bind(sSocket,(sockaddr*)&addr, sizeof(addr));
	if (-1 == r)
	{
		printf("绑定失败:%d\n",GetLastError());
		// 8 断开连接
		closesocket(sSocket);
		// 9 清理协议版本信息
		WSACleanup();
		return -2;
	}
	printf("绑定成功!\n");


	// 5.  监听
	r = listen(sSocket,10);
	if (-1 == r)
	{
		printf("监听失败:%d\n",GetLastError());
		// 8 断开连接
		closesocket(sSocket);
		// 9 清理协议版本信息
		WSACleanup();
		return -2;
	}
	printf("监听成功!\n");

	// 6 等待客户端连接
	SOCKET cSocket = accept(sSocket,NULL,NULL);
	if (SOCKET_ERROR == cSocket)
	{
		printf("服务器崩溃:%d\n",GetLastError());
		// 8 断开连接
		closesocket(sSocket);
		// 9 清理协议版本信息
		WSACleanup();
		return -2;
	}
	printf("有客户端连接上服务器了!\n");

	// 7 通信
	char buff[256] = {0};
	while (1)
	{
		r = recv(cSocket,buff,255,NULL);    // 从客户端接收数据
		if (r>0)
		{
			buff[r] = 0;  // 添加结束符号
			printf(">>%s\n",buff);  // 输出
		}

	}


	while (1);
	return 0;
}

Client.cpp

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include<Windows.h>
#include<stdio.h>
#include<iostream>

int main()
{
	// 1. 确定协议版本
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		printf("请求的版本不是2.2版本!\n");
		WSACleanup();
		return -1;
	}

	printf("请求的版本为2.2版本!\n");


	// 2  创建socket
	SOCKET sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (SOCKET_ERROR == sSocket)
	{
		printf("创建socke失败 :%d\n", GetLastError());
		return -2;
	}
	printf("创建socke成功!\n");


	// 3 确定服务器的协议地址簇
	std::string ip = "127.0.0.1";
	int port = 8080;
	SOCKADDR_IN addr = { 0 };
	addr.sin_family = AF_INET; // 和socket函数第一个参数保持一致
	addr.sin_addr.S_un.S_addr = inet_addr(ip.c_str()); // 服务器IP地址
	addr.sin_port = htons(port);  // 


	// 4  连接
	int r = connect(sSocket, (sockaddr*)&addr, sizeof(addr));
	if (-1 == r)
	{
		printf("连接失败:%d\n", GetLastError());
		return -2;
	}
	printf("连接成功!\n");

	// 5.   通信
	char buff[256];
	while (1)
	{
		memset(buff, 0, 256); // 清空数组 
		printf("发送服务器信息:");
		scanf_s("%s", buff,sizeof(buff));
		send(sSocket, buff, strlen(buff), NULL);
	}


	while (1);
	return 0;
}

多个客户端连接同一个服务器

Server.cpp

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<WinSock2.h>
#include<WS2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
#include<Windows.h>
#include<stdio.h>
#include<string>

#define NUM 1024  // 最大连接客户端

SOCKET cSocket[NUM];

int count;

// 和客户端通信的函数
void tongxin(int idx);

int main()
{
	count = 0;

	// 1. 确定协议版本
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		printf("请求的版本不是2.2版本!\n");
		WSACleanup();
		return -1;
	}
	printf("请求的版本为2.2版本!\n");


	// 2  创建socket
	SOCKET sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);   //结构体
	if (SOCKET_ERROR == sSocket)
	{
		printf("创建socke失败 :%d\n",GetLastError());
		return -2;
	}
	printf("创建socke成功!\n");


	// 3 确定服务器的协议地址簇
	std::string ip = "127.0.0.1";
	int port = 8080;
	SOCKADDR_IN addr = {0};
	addr.sin_family = AF_INET; // 和socket函数第一个参数保持一致
	addr.sin_addr.S_un.S_addr = inet_addr(ip.c_str()); // 本机IP地址
	//addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 
	addr.sin_port = htons(port);  // 大小端转换  在10000左右
	//printf("addr =  %d \n",sizeof(addr));



	// 4  绑定
	int r = bind(sSocket,(sockaddr*)&addr, sizeof(addr));
	if (-1 == r)
	{
		printf("绑定失败:%d\n",GetLastError());
		// 8 断开连接
		closesocket(sSocket);
		// 9 清理协议版本信息
		WSACleanup();
		return -2;
	}
	printf("绑定成功!\n");


	// 5.  监听
	r = listen(sSocket,10);
	if (-1 == r)
	{
		printf("监听失败:%d\n",GetLastError());
		// 8 断开连接
		closesocket(sSocket);
		// 9 清理协议版本信息
		WSACleanup();
		return -2;
	}
	printf("监听成功!\n");

	// 6 等待客户端连接
	for(int i =0 ;i < NUM; i++)
	{
		cSocket[i] = accept(sSocket, NULL, NULL);
		if (SOCKET_ERROR == cSocket[i])
		{
			printf("服务器崩溃:%d\n", GetLastError());
			// 8 断开连接
			closesocket(sSocket);
			// 9 清理协议版本信息
			WSACleanup();
			return -3;
		}
		printf("有客户端连接上服务器了: %d \n",i);

		count++;

		// 创建线程和客户端通信
		CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)tongxin, (LPVOID)i, NULL, NULL);
	}




	while (1);
	return 0;
}


// 和客户端通信
void tongxin(int idx)
{
	// 7 通信

	char buff[256] = { 0 };
	int r;
	char temp[256];
	while (1)
	{
		r = recv(cSocket[idx], buff, 255, NULL);    // 从客户端接收数据
		if (r > 0)
		{
			buff[r] = 0;  // 添加结束符号
			printf(">>%d:%s\n",idx, buff);  // 输出

			// 发送给当前连上服务器的所有客户端
			memset(temp,0,256);
			sprintf(temp, "%d:%s",idx,buff);
			for (int i = 0; i < count; i++)
			{
				send(cSocket[i],temp,strlen(temp),NULL);
			}
		}

	}

}

Client.cpp

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include<Windows.h>
#include<stdio.h>
#include<iostream>


#include<graphics.h>  // easyX
SOCKET sSocket;
void scanfAndSend();

int main()
{
	initgraph(200,400,1); // 俩个窗口

	// 1. 确定协议版本
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		printf("请求的版本不是2.2版本!\n");
		WSACleanup();
		return -1;
	}

	printf("请求的版本为2.2版本!\n");


	// 2  创建socket
	sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (SOCKET_ERROR == sSocket)
	{
		printf("创建socke失败 :%d\n", GetLastError());
		return -2;
	}
	printf("创建socke成功!\n");


	// 3 确定服务器的协议地址簇
	std::string ip = "127.0.0.1";
	int port = 8080;
	SOCKADDR_IN addr = { 0 };
	addr.sin_family = AF_INET; // 和socket函数第一个参数保持一致
	addr.sin_addr.S_un.S_addr = inet_addr(ip.c_str()); // 服务器IP地址
	//addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 本机IP地址
	addr.sin_port = htons(port);  // 大小端转换  在10000左右


	// 4  连接
	int r = connect(sSocket, (sockaddr*)&addr, sizeof(addr));
	if (-1 == r)
	{
		printf("连接失败:%d\n", GetLastError());
		return -2;
	}
	printf("连接成功!\n");

	CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)scanfAndSend,NULL,NULL,NULL);
	char buff[256];
	int n = 0;
	while (1)
	{
		r = recv(sSocket,buff,255,NULL);  // 循环从服务器接收
		if (r>0)
		{
			buff[r] = 0;// 添加结束符号
			// 显示到图形界面窗口
			outtextxy(1,n*20,buff);
			n++;
			if (n>18)
			{
				n = 0;
				cleardevice(); //清屏
			}
		}
	}


	while (1);
	return 0;

}


void scanfAndSend()
{
	// 5.   通信
	char buff[256];
	while (1)
	{
		memset(buff, 0, 256);    // 清空数组 
		printf("发送服务器信息:");
		scanf_s("%s", buff, sizeof(buff));   // 从命令行窗口接收发给服务器
		send(sSocket, buff, strlen(buff), NULL);
	}
}

参考:

https://www.bilibili.com/video/BV12u411r7J6/?spm_id_from=333.788.top_right_bar_window_custom_collection.content.click&vd_source=701c26bdba61a7e00f00852c31111c06

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: TCP通信demo是指基于TCP协议实现的通信示例程序。TCP协议是一种可靠的、面向连接的传输层协议,它的主要特点是在通信双方建立连接后,可保证数据的完整性、有序性和可靠性,在数据传输过程中还可以进行流量控制和拥塞控制,因此在网络传输中得到广泛的应用。 在实现TCP通信demo的过程中,需要注意以下几个方面: 1.连接建立:在TCP协议中,连接的建立需要经过三次握手的过程,即发送SYN报文、收到SYN+ACK报文、发送ACK报文。因此,在demo中需要实现连接建立的过程,并保证建立成功后才能进行数据传输。 2.数据传输:在TCP协议中,数据是分段传输的,每个数据包都有一个序号和确认序号。因此,在demo中需要实现数据的分段传输和接收,并进行序号和确认序号的匹配。 3.流量控制和拥塞控制:在TCP协议中,为了避免网络拥塞导致数据传输的失败,需要进行流量控制和拥塞控制。在demo中可以实现简单的流量控制和拥塞控制,例如设置最大传输速度和传输窗口大小。 总之,TCP通信demo是一个重要的网络编程示例程序,它可以帮助我们了解TCP协议的工作原理和应用场景,提高我们的网络编程技能和调试能力。 ### 回答2: TCP通信是计算机网络中重要的传输层协议,用于在两个设备之间提供可靠的数据传输。编写一个TCP通信的demo是帮助理解TCP协议及其应用的一种方式。以下是一份简单的TCP通信demo的说明: 该demo包含两个客户端和一个服务器端。客户端向服务器发送数据,服务器接收数据并返回响应。客户端与服务器之间通过一个连接在TCP协议下进行通信。客户端通过套接字socket()函数创建一个套接字,并使用connect()函数连接到服务器。服务器端也使用socket()函数创建套接字,并调用bind()函数绑定端口号,然后使用listen()函数开启监听模式。当客户端连接到服务器后,服务器端使用accept()函数接受连接请求,然后使用recv()函数接收客户端发送的数据,并使用send()函数发送响应。客户端通过send()函数发送数据,并使用recv()函数接收服务器端的响应。 在编写TCP通信demo时需要注意以下事项: 1. 客户端和服务器端需使用相同的协议族(如IPv4或IPv6)和协议类型(如TCP或UDP)。 2. 确定通信过程中所需的数据格式,并在客户端和服务器端之间使用相同的格式传输数据。 3. 需要注意TCP协议中的粘包问题,即多个数据包可能会被合并在一起,需要使用固定长度或特殊分隔符来区分数据包。 4. 在处理网络异常情况时,应考虑超时、连接失效等问题,并进行相应的异常处理。 通过编写TCP通信demo,可以更加深入理解TCP协议的工作原理和应用,加强网络编程的基本功。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值