用网络编程完成windows和linux跨平台之间的通信(服务器)

服务器代码逻辑:

服务器功能

  1. 创建 Socket:

    • 服务器首先创建一个 Socket 对象,用于进行网络通信。通常使用 socket() 函数创建。
  2. 绑定(Bind):

    • 服务器将 Socket 绑定到一个特定的 IP 地址和端口号上。这是通过 bind() 函数实现的,目的是告诉操作系统服务器将监听哪个 IP 地址和端口号上的连接请求。
  3. 监听(Listen):

    • 服务器将 Socket 设置为监听模式,准备接受来自客户端的连接请求。这是通过 listen() 函数实现的,通常需要指定一个待处理的连接队列的大小。
  4. 接受连接(Accept):

    • 服务器等待客户端的连接请求。当一个客户端请求连接时,服务器通过 accept() 函数接受连接,并为每个连接创建一个新的 Socket。服务器可以在不同的线程或进程中处理多个客户端连接。
  5. 处理数据(Read/Write):

    • 一旦连接建立,服务器和客户端可以通过已建立的 Socket 进行数据的读写操作。这是通过 recv() 和 send() 函数实现的。
  6. 关闭连接(Close):

    • 当数据传输完成或连接结束时,服务器使用 close() 函数关闭 Socket,释放资源。

windows打开服务器:

cpp 复制代码
#ifdef _WIN64
#define WIN32
#endif
#ifdef WIN32
#include <Windows.h>
#define socklen_t int
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define  closesocket close
#endif
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
#include<thread>

using namespace std;
class TcpThread
{
public:
	void Main()
	{
		char buf[1024] = { 0 };
		for (;;)
		{
			int recvlen = recv(client, buf, sizeof(buf) - 1, 0);
			//从客户端套接字 client 中接收数据,存储到缓冲区 buf 中。
			//sizeof(buf) - 1 确保缓冲区有足够的空间来存储数据,并保留一个字节用于存储终止符。



			if (recvlen <= 0 || strstr(buf, "quit") != NULL)
			{
				char re[] = "quit success!\n";
				send(client, re, strlen(re) + 1, 0);//发送"quit success!"消息到客户端,然后退出循环。
				break;
			}
			buf[recvlen] = '\0';
			int sendlen = send(client, "ok\n", 4, 0);
			printf("recv %s\n", buf);
		}

		closesocket(client);//关闭客户端套接字,释放相关资源。
		delete this;//删除当前 TcpThread 对象,释放内存。
	}
	int client = 0;
};
int main(int argc, char* argv[])
{
#ifdef WIN32
	/声明一个 WSADATA 结构体变量 ws。WSADATA 是一个结构体,包含了 Windows Sockets 动态链接库(DLL)的详细信息。
	WSADATA ws;
	//WSAStartup 函数初始化 Winsock 库。
	//MAKEWORD(2, 2) 是一个宏,它创建一个 16 位的值,表示我们请求的 Winsock 版本号。在这里,MAKEWORD(2, 2) 表示我们请求 Winsock 2.2 版本。
	//&ws 是指向 WSADATA 结构体的指针,用于接收初始化的信息。
	WSAStartup(MAKEWORD(2, 2), &ws);
#endif




	int sock = socket(AF_INET, SOCK_STREAM, 0);
	//AF_INET表示用的IPV4协议,SOCK_STREAM表示面向连接的稳定数据传输(TCP)
	if (sock == -1)
	{
		printf("create socket failed!\n");
		return -1;
	}
	unsigned short port = 8080;
	if (argc > 1)
	{
		port = atoi(argv[1]);
	}




	//端口号、ip地址
	sockaddr_in saddr;//sockaddr_in 是一个结构体类型,用于存储 IPv4 地址信息。

	saddr.sin_family = AF_INET;//表示IPV4
	saddr.sin_port = htons(port);//转换默认x86小端,host to net 
	saddr.sin_addr.s_addr = htonl(0);//将IP地址设置为 0.0.0.0,表示绑定到所有可用的网络接口。




	//--------------
	if (::bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0)
	{
		printf("bind port %d failed!\n", port);
		return -2;
	}
	printf("bind port %d success!\n", port);




	listen(sock, 10);//用于将套接字设为监听模式,使其可以接受传入的连接请求。10表示为套接字排队的最大连接个数




	for (;;)
	{
		sockaddr_in caddr;
		socklen_t len = sizeof(caddr);//socklen_t 是一个数据类型,用于表示套接字相关结构的大小
		int client = accept(sock, (sockaddr*)&caddr, &len);//成功时返回一个新的套接字文件描述符client,用于与已连接的客户端通信。
		if (client <= 0)break;
		printf("accept client %d\n", client);
		char* ip = inet_ntoa(caddr.sin_addr);//将 caddr.sin_addr 中存储的网络字节序的 IP 地址转换为点分十进制的字符串表示形式。
		unsigned short cport = ntohs(caddr.sin_port);//将 caddr.sin_port 中存储的网络字节序的端口号转换为主机字节序
		printf("client ip is %s,port is %d\n", ip, cport);



		TcpThread* th = new TcpThread();
		th->client = client;


		//创建一个新线程,并在该线程中执行 TcpThread 类的 Main 方法
		thread sth(&TcpThread::Main, th);//&TcpThread::Main 是指向 TcpThread 类成员函数 Main 的指针。th 是一个指向 TcpThread 对象的指针。
		sth.detach();
	}
	printf("%d", sock);
	closesocket(sock);
	return 0;
}

windows上直接运行该文件即可打开服务器等待客户端的连接

linux连接服务器:

在Putty上输入telnet 192.168.10.4 8080,telnet 192.168.10.4 8080 是一个命令,用于通过 Telnet 协议连接到指定的 IP 地址和端口号。具体来说,它尝试建立一个与 IP 地址 192.168.10.4 上端口 8080 的连接,如果你看到类似于"Connected to 192.168.10.4"这样的消息,说明端口 8080 上的服务正在监听,并且你已成功连接到该服务。这意味着你可以开始发送数据或与该服务交互。

注意 telnet后面的ip是服务器的ip,

当然我们也可以将服务器和客户端都在windows上或linux上打开,我只是为了说明可以跨平台通信而已。

在linux上编译运行服务器:

先进入该项目的文件夹,我的是test1项目文件夹,cd code, cd test1,在该文件夹下打开vim 编辑一个makefile,输入命令 vim makefile进入编辑页面,

然后输入make test1,即可编译成功,在.\ test1执行即可打开服务器

相关推荐
律宏阔4 小时前
WSL Docker 端口明明空闲,但就是绑不上端口
linux·windows
律宏阔4 小时前
Windows 禁用联想笔记本所有 Lenovo 后台服务
windows
律宏阔4 小时前
WSL 突然断网,无法 ping 内网或外网
linux·windows
穷人小水滴4 小时前
用容器编译 VirtualBox 虚拟机软件 (ArchLinux, podman)
linux·容器·virtualbox
乱码三千4 小时前
如何优雅地直连无公网 IP 的远程 GPU 服务器
linux·人工智能·程序员
yunwei374 小时前
使用 eBPF 跟踪 Nginx 请求
linux·后端·性能优化
yunwei374 小时前
使用 eBPF 跟踪 MySQL 查询
linux·后端·性能优化
yunwei374 小时前
eBPF 示例教程:使用 XDP 捕获 TCP 信息
linux·后端·性能优化
GeW5 小时前
制造业高端化,为什么必须重估Linux和数据库?
linux
GeW5 小时前
工业场景中的Linux与数据库选型:高端化转型的技术底座
linux