简单的服务器与客户端的连接(c++,TCP实现)

1.网络通信,首先计算机网络的基础知识得有,要了解TCP协议等等

2.在一个工程下建立一个新的项目Sever用作服务器,解释全写在代码中:


#include <winsock2.h>
#include <windows.h>
#include <tchar.h>
#include <iostream>
//所有的 Winsock 函数都是从 WS2_32.DLL 导出的,
//V在默认情况下并没有链接到该 库,如果想使用 Winsock API,
//就必须包含下边的库文件。
#pragma comment(lib,"Ws2_32.lib")
using namespace std;
//现在开发网络应用程序都使用 Winsock2
void _tmain()
{

	//初始化资源
	WSADATA  v1;               //这是一个结构体
	WSAStartup(MAKEWORD(2, 2) /*指定想要加载的 Winsock 库的版本,高字节为次版本号,低字节为主版本号*/ , &v1);


	//创建套接字
	SOCKET  ListenSocket; 
	//*internetwork: UDP, TCP, etc,地址家族*/
	//*这个就是使用TCP协议当然还有UDP协议*/
	//这个应该时再次确认协议
	ListenSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);//AF_INET(指IP地址家族),
	                                                        //SOCK_STREAM 流套接字,使用 TCP 提供有连接的可靠的传输 
					                       // IPPROTO_TCP再次用来指定使用的协议类型
	if (ListenSocket == INVALID_SOCKET)     //就是如果创建失败就是无效的套接字
	{
		goto Exit;
	}
	//初始化本地网卡
	/*
	sockaddr_in结构体
	struct sockaddr_in {      
		short   sin_family;           // 地址家族(即指定地址格式)应为 AF_INE,它告诉 Winsock 程序使用的是 IP 地址家族
		u_short sin_port;             // 端口号,最好从2048开始前边为公用的,最大到65 535 
		struct  in_addr sin_addr;     // IP 地址   
		char    sin_zero[8];         // 空字节,要设为 0 
	};
	端口号:
	*/
	sockaddr_in ServerAddress;
	ServerAddress.sin_family = AF_INET;
	ServerAddress.sin_port = htons(8888);   //此处指随便的一个空闲端口号,htons解释如下:

	/*
	sin_port 字段和 sin_addr 字段分别指定 套接字需要绑定的端口号和 IP 地址。
	放入这两个字段的数据的字节顺序必须是网络字节顺序。 因为网络字节顺序和 Intel CPU 的
	字节顺序刚好相反,所以必须首先使用 htons 函数进行转换
	*/

	ServerAddress.sin_addr.S_un.S_addr = INADDR_ANY;    // INADDR_ANY,系统会自动使用当前主机配置的所有 IP 地 址

	//绑定这个套接字到一个本地地址
	if (bind(ListenSocket, (sockaddr*)&ServerAddress, sizeof(sockaddr_in)) == SOCKET_ERROR)
	{
		goto Exit;
	}
	//listen 函数设置套接字ListenSocket进入监听状态
	listen(ListenSocket, 200);//200是指 监听队列中允许保持的尚未处理的最大连接数量 
	sockaddr_in ClientAddress = {0};
	SOCKET      ClientSocket;
	int ClientAddressLength = sizeof(sockaddr_in);
	CHAR BufferData[0x1000] = { 0 };

	//关于下边accept函数的解释

	/*
	SOCKET accept( 
		SOCKET s,                // 套接字句柄   
		struct sockaddr* addr,  // 一个指向 sockaddr_in 结构的指针,用于取得客户端的地址信息  
		int* addrlen            // 一个指向地址长度的指针 ); 
		
		该函数在 s 上取出未处理连接中的*****第一个连接*********,然后为这个连接创建新的套接字返回**** 它的句柄。
		**********新创建的套接字是处理实际连接的套接字,它
		与 s 有相同的属性。 程序默认工作在阻塞模式下,这种方式下如果没有
		未处理的连接存在 ,accept 函数会一 直等待下去,直到有新的连接发生才返回。  
		addrlen 参数用于指定 addr 所指空间的大小,也用于返回地址的实际长度。
		如果 addr 或 者 addrlen 是 NULL,则没有关于远程地址的信息返回
	*/
	while (1)
	{
		//************整个通信的过程是一个动态的交互过程**********
		
		//接收,accept 函数用于接受到来的连接,接受客户端的信息。

		//会直接等待直到客户端的启动函数才能执行
		ClientSocket = accept(ListenSocket, (sockaddr*)&ClientAddress, &ClientAddressLength); 
		
		char *TEXT = "已成功连接服务器!";

		//accept函数执行之后会进行send,向其中发送上述内容
		send(ClientSocket, TEXT, strlen(TEXT), 0); 

		 //存储,recv 函数从对方接收数据,并将其存储到指定的缓冲区


		 //当客户端进行输入并才执行recv函数,接收客户端的输入信息
		int nrecv=recv(ClientSocket, BufferData/*要收到数据的缓冲区地址*/, 0x1000/*缓冲区的大小*/, 0);
		if (nrecv)
		{
			cout << "收到客户端的信息:" << endl;
			cout << endl;
		}
		printf("%s\r\n", BufferData);//打印
		nrecv = 0;
		closesocket(ClientSocket);
	}
Exit:	
	_tprintf(_T("Input AnyKey To Exit\r\n"));
}

3.在工程下再建立一个新的项目Client用作客户端:

#include <winsock2.h>           
#include <windows.h>
#include <tchar.h>
#include <iostream>

#pragma comment(lib,"Ws2_32.lib")  
using namespace std;
void _tmain()
{
	//初始化资源
	WSADATA  v1;
	WSAStartup(MAKEWORD(2, 2), &v1);
	//创建套接字
	SOCKET  ClientSocket;  //int a
	ClientSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
	if (ClientSocket == INVALID_SOCKET)
	{
		goto Exit;
	}
	//初始化本地网卡
	sockaddr_in ServerAddress;
	ServerAddress.sin_family = AF_INET;
	ServerAddress.sin_port = htons(8888);
	ServerAddress.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");    // 注意,这里要填写服务器程序(TCPServer 程序)所在机器的 IP 地址 ,这里是本机
	CHAR BufferData[0x1000] = { 0 };
	while (1)
	{
		//客户端程序在创建套接字之后,要使用 connect 函数请求与服务器连接,服务器那边accept函数才开始执行
		connect(ClientSocket, (sockaddr*)&ServerAddress, sizeof(sockaddr_in));
		char whatrecv[20];
		
		//服务器的send函数执行后,客户端recv接收信息
		int nrecv = recv(ClientSocket,whatrecv,20,0);
		if (nrecv)
		{
			whatrecv[nrecv] = '\0';
			cout << whatrecv << endl;
		}
		cout << "请输入发送到服务器的字符信息:" ;
		scanf("%s",BufferData);
		int v1 = strlen(BufferData) + 1;        //把“/0”的长度也算上

		//向服务器发送信息,服务器的recv准备接收
		send(ClientSocket, BufferData,v1,0);	
		closesocket(ClientSocket);
	}
Exit:	
	_tprintf(_T("Input AnyKey To Exit\r\n"));

}

4.分别右击两个项目名称,进行  重新生成  ,然后在工程的根目录下找到Debug文件夹,找到应用程序(exe)Sever和Client,

先双击Sever,后双击Client,

一定记住这样,下边是运行之后的图片:

发布了37 篇原创文章 · 获赞 12 · 访问量 9264

猜你喜欢

转载自blog.csdn.net/weixin_43265881/article/details/96902086
今日推荐