C/S架构,服务端和客户端的连接,没有用类封装,C语言风格的C++代码,编译环境VS2022
新建一个文件,然后如图,新建一个C++空项目
下一步是找到该vs文件保存的路径,新建一个tcpSocket文件夹,在tcpSocket文件夹里面新建一个tcpSocket.h和tcpSocket.cpp文件
然后回到VS,分别在两个解决方案这里添加现有项,选择刚创建的两个文件,顺手添加两个源文件
然后在Client.cpp和Server.cpp里面添加头文件
#include "../tcpSocket/tcpSocket.h"
接下来就是编写tcpSocket.h文件了
#pragma once
#ifndef _TCPSOCKET_H_
#define _TCPSOCKET_H_
#include
#include
//网络编程,要引用这两个
#include
#pragma comment(lib, "ws2_32.lib")
//后续的连接端口,0~65535,但是在定义时建议使用10000以上的端口,因为存在端口保留和占用的情况
#define PORT 65533
//定义一个err函数,方便后续debug时根据最后的错误获取信息
#define err(errMsg) printf("[line: %d]%s failed code %d\n", __LINE__, errMsg, WSAGetLastError())//该函数用来获取WSA最后发生错误的代码
using namespace std;
//打开网络库
bool init_Socket();
//关闭网络库
bool close_Socket();
//创建服务端socket
SOCKET CreatServerScoket();
//创建客户端socket
SOCKET CreatClientScoket(const char* ip);
#endif // !_TCPSOCKET_H
然后是tcpSocket.cpp文件
#include "tcpSocket.h"
bool init_Socket()
{
WSADATA data;
if (WSAStartup(MAKEWORD(2, 2), &data) != 0)
//Windows socket async :Windows异步套接字,使用前必须要对其进行初始化
{
err("WSAStartup");
return false;
}
return true;
}
bool close_Socket()
{
if (WSACleanup() != 0)
//使用完了要关闭网络库
{
err("WSACleanup");
return false;
}
return true;
}
SOCKET CreatServerScoket()
{
//1、创建空的socket
/*
parm1:AF 地址协议族 IPv4, IPv6
parm2:type 地址协议类型 流式套接字, 数据报
parm3:protocol 使用具体的某个传输协议
*/
SOCKET fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd == INVALID_SOCKET)
{
err("SOCKET");
}
//2、绑定ip地址和端口号
struct sockaddr_in addr;
addr.sin_family = AF_INET;//和创建时要一样
addr.sin_port = htons(PORT); //把主机字节顺序转换为网络字节顺序
addr.sin_addr.S_un.S_addr = ADDR_ANY;//inet_addr("127.0.0.1")
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
err("bind");
return false;
}
//3、监听电话:
listen(fd, 10);
return fd;
}
SOCKET CreatClientScoket(const char* ip)
{
//1、创建空的socket
/*
parm1:AF 地址协议族 IPv4, IPv6
parm2:type 地址协议类型 流式套接字, 数据报
parm3:protocol 使用具体的某个传输协议
*/
SOCKET fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd == INVALID_SOCKET)
{
err("SOCKET");
}
//2、绑定ip地址和端口号
struct sockaddr_in addr;
addr.sin_family = AF_INET;//和创建时要一样
addr.sin_port = htons(PORT); //把主机字节顺序转换为网络字节顺序
addr.sin_addr.S_un.S_addr = inet_addr(ip);
//3、与服务器建立连接
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == INVALID_SOCKET)
{
err("connect");
return false;
}
return fd;
}
下一步先写Server服务端
#include "../tcpSocket/tcpSocke.h"
int main()
{
init_Socket();//初始化网络库
SOCKET serfd = CreatServerScoket();//创建服务端socket
cout << "wait client connect...\n";
SOCKET clifd = accept(serfd, NULL, NULL); //如果有客户端请求连接
if (clifd == INVALID_SOCKET)//失败就输出如下错误
{
err("accept");
}
char buf[BUFSIZ * 2] = { 0 };//定义接收缓冲区并初始化
if (recv(clifd, buf, BUFSIZ, 0) > 0)//接受并输出
{
cout << buf << endl;
}
memset(buf, 0, sizeof(buf));//缓冲区初始化,防止后续重复输出
close_Socket();
return 0;
}
下一个是客户端
#include "../tcpSocket/tcpSocket.h"
int main()
{
init_Socket();//创建客户端socket
SOCKET fd = CreatClientScoket("127.0.0.1");//连接
char str[] = "connect success";//连接成功
send(fd, str, strlen(str), 0);
closesocket(fd);//关闭客户端socket
close_Socket();//WSACleanup
}
这样就完成了,接下来想要输出更多内容,可以自行使用send和recv函数进行
在debug时,首先将server设置为启动项目,然后CTRL+F5运行server
接下来如图所示,运行client
对于debug时报这样的错误,有两种解决方案,第一个是复制这段错误代码,然后在引用的头文件最开始处定义宏
或者是在client属性之中,C/C++中关闭SDL检查,服务端和客户端都要关闭才行
参考:C/C++基础教程:详细讲解socket网络编程上_哔哩哔哩_bilibili
C/C++基础教程:详细讲解socket网络编程(中)_哔哩哔哩_bilibili
C/C++基础教程:详细讲解socket网络编程(下 )_哔哩哔哩_bilibili