Windows下TCP协议C++

服务器:

#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "WS2_32")
//#include<stdio.h>

using namespace std;

int main()
{
	//1.启动SOCKET库,版本为2.0
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD(2, 0);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0)
	{
		cout << "Socket2.0初始化失败,Exit!";
		return 0;
	}
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0)
	{
		WSACleanup();
		return 0;
	}

	//2.创建套接字,用于监听
	SOCKET sock;
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock == INVALID_SOCKET)
	{
		cout << "Socket 创建失败,Exit!";
		return 0;
	}

	//3.绑定
	SOCKADDR_IN myaddr; //sockaddr_in相当于sockaddr结构
	memset(&myaddr, 0, sizeof(myaddr));//初始化  清零 
	myaddr.sin_family = AF_INET;//只能为这个值
	myaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//将u_long型转换为网络字节序列
	myaddr.sin_port = htons(7861);// 将u_short型转换为网络字节序列

	bind(sock, (SOCKADDR*)&myaddr, sizeof(myaddr));//绑定套接字

	//4.设置监听
	listen(sock, 5);

	//5.等待并接受数据
	SOCKADDR_IN addrClient;
	int len = sizeof(SOCKADDR);
	//char buf[256] = "";
	int number = 0;	
	while (true) {
		SOCKET sockConnect = accept(sock, (SOCKADDR*)&addrClient, &len);
		cout << "与IP地址:" << inet_ntoa(addrClient.sin_addr) << "建立连接。" << endl;

		while (true) {
			char sendBuf[100];
			sprintf(sendBuf, "欢迎%s%s%d!!", inet_ntoa(addrClient.sin_addr), "客户端", ++number);
			//发送
			//send(sockConnect, sendBuf, strlen(sendBuf) + 1, 0);
			if (send(sockConnect, sendBuf, strlen(sendBuf) + 1, 0) == SOCKET_ERROR) {
				cout << "发送失败,可能是客户端已关闭" << endl;
				break;
			}

			//接收
			char recvBuf[100];
			if (recv(sockConnect, recvBuf, 100, 0) == -1)//TCP CLIENT端关闭后,服务器端的recv会一直返回-1,此时如果不退出,服务端recv会一直接收
			{
				cout << "接收失败,可能是客户端已关闭" << endl;
				break;
			}
			else {
				cout << "IP地址:" << inet_ntoa(addrClient.sin_addr) << "的客户端发来消息:";
				cout << recvBuf << endl;
				//printf("%s\n", recvBuf);
			}
			memset(recvBuf,0, sizeof(recvBuf));//把接收的数据清空
			Sleep(2000);
		}
		closesocket(sockConnect);
	}

	//??这两个条件?
	//if (!closesocket(sock))
	//{
	//	WSAGetLastError();
	//	return 0;
	//}
	//if (!WSACleanup())
	//{
	//	WSAGetLastError();
	//	return 0;
	//}

	cout << "服务器关闭" << endl;
	closesocket(sock);
	WSACleanup();
	return 0;
}


客户端:

#include <winsock2.h>
#pragma comment(lib, "WS2_32")
#include <iostream>

using namespace std;

int main()
{
	//1.启动SOCKET库,版本为2.0
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD(2, 0);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0)
	{
		cout << "Socket2.0初始化失败,Exit!";
		return 0;
	}
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0)
	{
		WSACleanup();
		return 0;
	}


	//2.创建socket,
	SOCKET sock;                   //socket
	sock = socket(
		AF_INET,           //internetwork: UDP, TCP, etc
		SOCK_STREAM,        //TCP
		0                  //protocol
	);

	if (sock == INVALID_SOCKET) {
		cout << "Socket 创建失败,Exit!";
		return 0;
	}

	//3.设置发往的地址
	SOCKADDR_IN addrto;            //发往的地址	
	memset(&addrto, 0, sizeof(addrto));
	addrto.sin_family = AF_INET;

	// https://jingyan.baidu.com/article/1709ad8041dca64634c4f006.html
	//去掉SDL检查。设置项目属性,将c/c++->SDL检查设置为“否”即可跳过检查,使用旧的函数可编译成功。
	addrto.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //旧函数,不设置sdl检查会报错

	//端口号必须和服务器绑定的端口号一致
	addrto.sin_port = htons(7861);
	//申请链接服务器
	connect(sock, (SOCKADDR*)&addrto, sizeof(SOCKADDR));

	int n=0;
	while (true) {
		char recvBuf[100];
		recv(sock, recvBuf, 100, 0);
		cout << recvBuf << endl;

		char sendBuf[100];
		sprintf(sendBuf, "你好,我是客户端%d", ++n);
		send(sock, sendBuf, 100, 0);
		Sleep(1000);

		if (n > 10)break;
	}

	Sleep(5000);

	//if (!closesocket(sock))
	//{
	//	WSAGetLastError();
	//	return 0;
	//}
	//if (!WSACleanup())
	//{
	//	WSAGetLastError();
	//	return 0;
	//}

	cout << "客户端关闭" << endl;
	closesocket(sock);
	WSACleanup();
	return 0;
}

运行结果:

启动了两次客户端,两次均正常连接

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值