前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >c++简单网络编程基础(1)简单服务器

c++简单网络编程基础(1)简单服务器

原创
作者头像
ys.h
发布2023-12-14 13:55:22
2871
发布2023-12-14 13:55:22
举报
文章被收录于专栏:c++网络编程

TCP/IP协议基础

首先要学习网络编程最基础的就是要理解TCP/IP协议,可以去网上找找类似文章理解一下。

接下来我们来进行简单的c++网络编程编码。

(1)Windows中进行c++网络编程前提

代码语言:c++
复制
#include<WinSock2.h>//头文件
#pragm/a comment(lib , "ws2_32")//依赖库包含
// 1. 建立网络连接协议
WSADATA data;
if (WSAStartup(MAKEWORD(2, 2), &data) != 0) 
{
	std::cout << "Could not startup" << '\n';
}

(2)SOCKET(句柄 ,也叫套接字)

什么是句柄呢?教我的老哥是这样说的,网络中通信是需要地址的,句柄就相当于是你在小区哪一栋和你的门牌号,也就是ip和端口。接下来我们插入创造句柄的代码:

代码语言:c++
复制
//2. 创造套接字
int server_sock = socket(AF_INET , SOCK_STREAM , 0);//AF_INET是TCP/IP--IPv4一般情况下管用
//,SOCK_STREAM是TCP流,0是默认适配句柄和协议族
if (server_sock == INVALID_SOCKET)
{
	std::cout << "error sock!" << "\n";
	return 0;
}
std::cout << "1.  sock is ok !" << "\n";

(3)bind(绑定ip和端口,将服务器的句柄确认)

bind(SOCKET sock , sockaddr* addr , int namelen);

第一个sock是本机服务器的句柄,第二个是存放ip和端口和协议族的结构体(可以先这样理解),第三个就是addr的字节大小,如果后续连接的客户端字节大小不一的话就会报错。

具体代码如下:

代码语言:c++
复制
//3.绑定ip , 端口
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);//将主机字节顺序转换为网络字节顺序
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //将点分十进制的IPv4地址转换成网络字节序列的长整型
int addr_len = sizeof(addr);
if (bind(server_sock, (sockaddr*)&addr, addr_len) == SOCKET_ERROR) {
	std::cout << "error bind!" << "\n";
	return 0;
}
std::cout << "2.  bind is ok!" << "\n";

(4)listen(监听句柄,相当于把自己的家的门打开让外人可以进来)

listen(SOCKET sock , int backlog)

第一个sock是本机服务器的句柄,第二个backlog是什么呢,backlog是挂起队列的最大长度,

具体理解是当你的服务器只能接收10个人,这时有30个人想进去你的服务器,剩下的20人你不可能不理人家把,这个就是系统创造的队列长度,将剩下20个人放进队列,后续一个一个连接,我们一般填写这个参数为SOMAXCONN让本机自己选择合适的个数。

具体代码如下:

代码语言:c++
复制
//4.监听(打开大门)
if (listen(server_sock, SOMAXCONN) == SOCKET_ERROR) {
	std::cout << "error listen!" << "\n";
	return 0;
}
std::cout << "3.  listen is ok!" << "\n";

(5)accept接收客户端

accept(SOCKET sock ,sockaddr* addr ,int* addrlen);

第一个sock是服务端的sock,第二个addr是什么呢?这个addr是服务端为客户端连接分配的ip和端口,addrlen是分配的addr的字节大小;这个函数返回的值是一个SOCKET类型的值,也就是服务端为客户端连接而分配的句柄值。

我们今天只讲接收客户端连接,不讲接收客户端数据

具体代码如下:

代码语言:c++
复制
//5接收客户端
while (true) {
	SOCKADDR_IN client_addr;
	int client_addr_len = sizeof(SOCKADDR_IN);
	int client_sock = accept(server_sock, (sockaddr*)&client_addr, &client_addr_len);
	
	if (SOCKET_ERROR == client_sock) {
		std::cout << "error accept" << "\n";
		return 0;
	}
	std::cout << "sock[" << client_sock << "]  ip[" << inet_ntoa(client_addr.sin_addr) << "]  port[" << ntohs(client_addr.sin_port)
		<< "]\n";
	std::thread t(Smallt , client_sock);//创造一个线程来对客户端进行数据的接收
	t.detach();
	
}

整段可运行代码如下:

代码语言:c++
复制
#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include<iostream>
#include<WinSock2.h>
#pragma comment(lib , "ws2_32")
#include<WS2tcpip.h>
#include<thread>


void Smallt(int csock) 
{	
	while (true) {
		char buff[1024] = { 0 };
		int recv_len = recv(csock, buff, 1024, 0);
		if (recv_len <= 0) {
			std::cout << "close socket" << "\n";
			closesocket(csock);
			break;
		}
		
		std::cout << "recv >>>>> " << buff << "\n";
		send(csock, buff, recv_len, 0);
	}
	return;
}

int main() 
{
	// 1. 建立网络连接协议
	WSADATA data;
	if (WSAStartup(MAKEWORD(2, 2), &data) != 0) 
	{
		std::cout << "Could not startup" << '\n';
	}

	//2. 创造套接字
	int server_sock = socket(AF_INET , SOCK_STREAM , 0);//AF_INET是TCP/IP--IPv4一般情况下管用,SOCK_STREAM是TCP流,0是默认适配句柄和协议族
	if (server_sock == INVALID_SOCKET)
	{
		std::cout << "error sock!" << "\n";
		return 0;
	}
	std::cout << "1.  sock is ok !" << "\n";

	//3.绑定ip , 端口
	SOCKADDR_IN addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8080);//将主机字节顺序转换为网络字节顺序
	addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //将点分十进制的IPv4地址转换成网络字节序列的长整型
	int addr_len = sizeof(addr);
	if (bind(server_sock, (sockaddr*)&addr, addr_len) == SOCKET_ERROR) {
		std::cout << "error bind!" << "\n";
		return 0;
	}

	std::cout << "2.  bind is ok!" << "\n";

	//4.监听(打开大门)
	if (listen(server_sock, SOMAXCONN) == SOCKET_ERROR) {
		std::cout << "error listen!" << "\n";
		return 0;
	}
	std::cout << "3.  listen is ok!" << "\n";

	//5接收客户端
	while (true) {
		SOCKADDR_IN client_addr;
		int client_addr_len = sizeof(SOCKADDR_IN);
		int client_sock = accept(server_sock, (sockaddr*)&client_addr, &client_addr_len);
		
		if (SOCKET_ERROR == client_sock) {
			std::cout << "error accept" << "\n";
			return 0;
		}
		std::cout << "sock[" << client_sock << "]  ip[" << inet_ntoa(client_addr.sin_addr) << "]  port[" << ntohs(client_addr.sin_port)
			<< "]\n";
		std::thread t(Smallt , client_sock);//创造一个线程来对客户端进行数据的接收
		t.detach();
		
	}


	closesocket(server_sock);//关闭服务端

	WSACleanup();//
	return 0;
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • TCP/IP协议基础
  • (1)Windows中进行c++网络编程前提
  • (2)SOCKET(句柄 ,也叫套接字)
  • (3)bind(绑定ip和端口,将服务器的句柄确认)
  • (4)listen(监听句柄,相当于把自己的家的门打开让外人可以进来)
  • (5)accept接收客户端
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档