略,网上有很多这样的知识,我觉得他们应该讲的比我好。我是跟着韩国人尹圣雨写的《TCP/IP网络编程》这本书学的。
C++11 std::thread
在经过自己简单的封装
因为我也是初学,可能写的不好,封装的也不好,我写这篇文章,只是希望帮助很基础的初学者,慢慢的接触socket,也给自己记录一下学习的经过。
所以,如果错误的,或者不好的地方,望各位多多包涵,一起学习。
我是使用cMake构建项目的,我也只会很简单很简单的,这里就不贴出来了。如你不会的话,就直接用g++编译就好了。(可以百度一下g++多文件的编译)
这个我分为五篇文章,每篇文章是一个完整的项目
第一个是基础版的,也就是进行简单的封装,客户端连接服务端(仅限一个),做一个回声服务器。
第二个是使用多进程服务器,可进行多用户的连接。
第三个是使用select函数。
第四个是使用epoll。
第五个是多线程服务器。
客户端
/*================================================================
* Copyright (C) 2021 ymbLite. All rights reserved.
*
* 文件名称:TcpClient.h
* 创 建 者:ymbLite
* 创建日期:2021年11月03日
* 描 述:
*
================================================================*/
#ifndef _TCPCLIENT_H
#define _TCPCLIENT_H
#include
#include
#include
#include
#include
#include
#include
#define BUFF_SIZE 1024
using std::cout;
using std::cin;
using std::endl;
using std::string;
class TcpClient{
private:
int clnt_sock; //客户端的socket
struct sockaddr_in serv_addr; //客户端的连接服务器的网络地址结构
char buf[BUFF_SIZE]; //客户端的读写缓冲区
int buf_len; //客户端的读写长度
public:
TcpClient();//构造函数
~TcpClient();//析构函数
/**
* 初始化客户端
* ip_addr: ipv4的地址
* port: 通信的端口号
*/
bool InitClient();
/*
* 连接服务器
* */
bool Connect(const string& ip_addr , const string& post);
/*
* 读取缓冲区的数据
* */
int Read();
/*
* 写入数据
* str:需要发送的数据
* */
void Write(const string& str);
/*
* 关闭socket
* */
void CloseClientSock();
};
#endif //TCPCLIENT_H
/*================================================================
* Copyright (C) 2021 ymbLite. All rights reserved.
*
* 文件名称:TcpClient.cpp
* 创 建 者:ymbLite
* 创建日期:2021年11月03日
* 描 述:
*
================================================================*/
#include "TcpClient.h"
in_addr GetHostByName(const string& ip_addr){
struct hostent* host;
host = gethostbyname(ip_addr.c_str());
struct in_addr _sin_addr;
memset(&_sin_addr , 0 , sizeof(_sin_addr));
if(!host){
return _sin_addr;
}
_sin_addr = (*(struct in_addr*)host->h_addr_list[0]);
return _sin_addr;
}
TcpClient::TcpClient():clnt_sock(-1),buf_len(0){
}
TcpClient::~TcpClient(){
}
bool TcpClient::InitClient(){
if(clnt_sock != -1){
CloseClientSock();
}
clnt_sock = socket(PF_INET , SOCK_STREAM , 0);
if(clnt_sock == -1){
cout<<"客户端创建socket失败,socket() error!"< 0){
close(clnt_sock);
}
clnt_sock = -1;
}
/*================================================================
* Copyright (C) 2021 ymbLite. All rights reserved.
*
* 文件名称:main.cpp
* 创 建 者:ymbLite
* 创建日期:2021年11月03日
* 描 述:
*
================================================================*/
#include "TcpClient.h"
int main(int argc , char* argv[]){
TcpClient tcp_client;
bool ope_res = tcp_client.InitClient();
if(!ope_res){
return -1;
}
ope_res = tcp_client.Connect(argv[1] , argv[2]);
if(!ope_res){
return -2;
}
cout<<"开始发送数据(输入q退出)"<>str;
if(!strcmp(str.c_str() , "q")){
break;
}
tcp_client.Write(str);
if(tcp_client.Read() <= 0){
break;
}
}
tcp_client.CloseClientSock();
return 0;
}
服务端
/*================================================================
* Copyright (C) 2021 ymbLite. All rights reserved.
*
* 文件名称:TcpServer.h
* 创 建 者:ymbLite
* 创建日期:2021年11月03日
* 描 述:socket编程中,简单的TCP服务端
*
================================================================*/
#ifndef _TCPSERVER_H
#define _TCPSERVER_H
#include
#include
#include
#include
#include
#include
#define BUFF_SZIE 1024
using std::cout;
using std::endl;
using std::cin;
using std::string;
class TcpServer{
private:
struct sockaddr_in serv_addr;//服务器中服务端的网络地址结构
struct sockaddr_in clnt_addr;//服务端中客户端的网络地址结构
socklen_t clnt_addr_len;//服务器中客户端的网络地址结构的长度
char buf[BUFF_SZIE];//读写缓冲区
int buf_len;//读取的字节长度
public:
int serv_sock;//服务器中服务端的socket描述符
int clnt_sock;//服务器中客户端的socket描述符
private:
public:
//构造函数
TcpServer();
//析构函数
~TcpServer();
/*
* 初始化服务器
* 服务端地址使用INADDR_ANY
* port:端口号
* */
bool InitServer(const string& port);
/*
* 阻塞接受客户端的连接
* */
bool Accept();
/**
* 关闭服务器中服务端的套接字
*/
void CloseServerSock();
/*
* 关闭服务器中客户端的套接字
* */
void CloseClientSock();
/*
* 读取客户端的数据
* */
int Read();
/**
* 回写客户端的数据
*/
void Write();
};
#endif //TCPSERVER_H
/*================================================================
* Copyright (C) 2021 ymbLite. All rights reserved.
*
* 文件名称:TcpServer.cpp
* 创 建 者:ymbLite
* 创建日期:2021年11月03日
* 描 述:
*
================================================================*/
#include "TcpServer.h"
TcpServer::TcpServer():serv_sock(-1),clnt_sock(-1){
cout<<"TCP服务器的构造函数"< 0){
CloseServerSock();
serv_sock = -1;
}
//创建服务器中的服务端socket
serv_sock = socket(PF_INET , SOCK_STREAM , 0);
if(serv_sock == -1){
cout<<"服务器创建监听套接字失败,socket() error!"< 0){
close(serv_sock);
serv_sock = -1;
}
}
void TcpServer::CloseClientSock(){
if(clnt_sock > 0){
close(clnt_sock);
serv_sock = -1;
}
}
int TcpServer::Read(){
if(clnt_sock == -1){
cout<<"未有客户端进行连接"<
/*================================================================
* Copyright (C) 2021 ymbLite. All rights reserved.
*
* 文件名称:main.cpp
* 创 建 者:ymbLite
* 创建日期:2021年11月03日
* 描 述:
*
================================================================*/
#include "TcpServer.h"
int main(int argc ,char* argv[]){
if(argc != 2){
cout<<"Usage : "<"<
我是把项目分成了客户端和服务端,如果初学者,可以直接复制进去,进行编译,就可以运行了,我代码必要的地方都会注释,希望能帮助到你。