Linux下基于C++11的socket网络编程(线程版本)
第一:关于C++11的线程操作
哈哈,百度这个比较直接,可以很清楚的告诉你。
第二:声明
不再追溯,可以先看看(基础版本)(进程版本)(select函数版本)(epoll版本)再看这个,谢谢。
工具类我也不再写,可以查看(进程版本),一模一样,直接复制过来就可以用了。
客户端也和(进程版本)一样,所以后面的文章,就不再写客户端。
第三:代码
工具类:略,看声明
客户端:略,看声明
服务端
/*================================================================
* Copyright (C) 2021 ymbLite. All rights reserved.
*
* 文件名称:TcpServer.h
* 创 建 者:ymbLite
* 创建日期:2021年11月03日
* 描 述:socket编程中,简单的TCP服务端
*
================================================================*/#ifndef _TCPSERVER_H
#define _TCPSERVER_H#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string>
#include <vector>
#include <cstring>
#include <unistd.h>
#include <mutex>
#include <thread>#include "BaseUtil.h"const int BUFF_SIZE = 1024; //最多可以接受的字节数
const int MAX_CLIENT = 10; //最多允许10个客户端的同时连接using std::cout;
using std::endl;
using std::cin;
using std::string;
using std::vector;//自定义套接字的描述信息
struct descript_socket{int sockfd = -1; //socket描述符string ip_addr = ""; //ip地址int id = -1; //sock的编号};class TcpServer{private:struct sockaddr_in serv_addr; //服务器中服务端的网络地址结构struct sockaddr_in clnt_addr; //服务端中客户端的网络地址结构socklen_t clnt_addr_len; //服务器中客户端的网络地址结构的长度int m_buflen; //调用Read方法后,读取的子接大小,单位是子接//关于线程的成员变量int socket_id = 0; //C++11之后,可以在这里进行初始化std::mutex _mutex; //互斥量vector<descript_socket*> _descript_socket;//保存连接的socket数据public:int serv_sock; //服务器中服务端的socket描述符int clnt_sock; //服务器中客户端的socket描述符private:/** 阻塞接受客户端的连接* return* -1:客户端连接失败 * 0:服务端未开启socket服务 * >0:成功接受一个客户端的连接,返回的是客户在服务端中的socket描述符* */int Accept();/** 回声线程* */void EchoThread(descript_socket* _descript_socket);public://构造函数TcpServer();//析构函数~TcpServer();/** 初始化服务器* 服务端地址使用INADDR_ANY* port:端口号* */bool InitServer(const string& port);/** 接收客户端发送过来的数据* buffer :接受数据缓冲区的地址,数据的长度保存在m_buflen成员变量中* timeout :等待数据的超时时间,单位为秒,缺省为0-无限等待* * return :true-成功,false-失败,失败的情况有两种,1)超时等待,2)socket连接不可用* */bool Read( char* buffer , const int timeout = 0);/** 向客户端写入数据** buffer :带发送数据的缓冲区地址* ibuflen :待发送数据的大小,单位:字节,缺省值为0,* 如果是ascii字符串,ibuflen取0* 如果是二进制数据流,那么ibuflen就取数据块的大小** return :true-成功,false-失败,失败原因为socket连接不可用* */bool Write(const char* buffer , const int ibuflen = 0);/** 开始接受客户端的请求,并且创建线程* */int StartCreateThread();/*** 关闭服务器中服务端的套接字*/void CloseServerSock();/** 关闭服务器中客户端的套接字* */void CloseClientSock();};
#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){
}TcpServer::~TcpServer(){CloseServerSock();
}bool TcpServer::InitServer(const string& port){//先判断服务端socket是否已开启if(serv_sock > 0){CloseServerSock();serv_sock = -1;}//创建服务器中的服务端socketserv_sock = socket(PF_INET , SOCK_STREAM , 0);if(serv_sock == -1){cout<<"服务器创建监听套接字失败,socket() error!"<<endl;return false;} //绑定服务端的socket到相应的网络地址结构中memset(&serv_addr , 0 , sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(atoi(port.c_str()));if(bind(serv_sock , (struct sockaddr*)& serv_addr , sizeof(serv_addr)) == -1){cout<<"服务器绑定套接字失败,bind() error!"<<endl;CloseServerSock();return false;}//开始监听服务端的套接字if(listen(serv_sock , 5) == -1){cout<<"服务端监听套接字失败,listen() error!"<<endl;CloseServerSock();return false;}cout<<"服务端初始化完成,开始接受客户端的连接..."<<endl;return true;
}int TcpServer::Accept(){//判断服务端是否已经开启了socketif(serv_sock == -1){cout<<"服务器中未开启监听的socket,Accept() error!"<<endl;return 0;}clnt_addr_len = sizeof(clnt_addr);clnt_sock = accept(serv_sock , (struct sockaddr*)& clnt_addr , &clnt_addr_len);return clnt_sock;
}void TcpServer::EchoThread( descript_socket* _descript_socket ){cout<<"Echo thread_id ["<<std::this_thread::get_id()<<"] Start Run..."<<endl;cout<<"[sockfd:"<<_descript_socket->sockfd<<"\tip_addr:"<<_descript_socket->ip_addr<<"\tid:"<<_descript_socket->id<<"]"<<endl;//开始接收客户端发送的信息int msg_len;char msg[BUFF_SIZE];while(TcpBaseRead(_descript_socket->sockfd , msg , &msg_len)){msg[msg_len] = 0;cout<<"【"<<_descript_socket->sockfd<<"】:"<<msg<<endl;if(!TcpBaseWrite(_descript_socket->sockfd , msg)){cout<<"消息发送失败,对端已关闭"<<endl;break;}}cout<<"【"<<_descript_socket->sockfd<<"】断开了连接.."<<endl;cout<<"Echo thread_id ["<<std::this_thread::get_id()<<"] Stop Run..."<<endl;//关闭连接close(_descript_socket->sockfd);
}int TcpServer::StartCreateThread(){//接受一个连接int _clnt_sock = Accept();if(_clnt_sock <= 0){cout<<"接受连接失败..."<<endl;return -1;}//连接成功//首先保存服务器连接的客户端信息descript_socket* ds = new descript_socket;ds->sockfd = _clnt_sock; //socket描述符ds->ip_addr = inet_ntoa(clnt_addr.sin_addr);//ip地址 ds->id = socket_id;_descript_socket.push_back(ds);//开启一个线程std::thread _thread(&TcpServer::EchoThread , this , ds);_thread.detach();//线程信息idsocket_id++;return 1;
}void TcpServer::CloseServerSock(){if(serv_sock > 0){cout<<"关闭了监听socket"<<endl;close(serv_sock);serv_sock = -1;}
}void TcpServer::CloseClientSock(){if(clnt_sock > 0){cout<<"关闭了连接socket"<<endl;close(clnt_sock);serv_sock = -1;}
}
/*================================================================
* 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 : "<<argv[0]<<" <PORT>"<<endl;return -1;}//创建服务端的socketTcpServer tcp_server;//初始化服务器bool init_res = tcp_server.InitServer(argv[1]);if(!init_res){cout<<"服务器初始化失败"<<endl;return -1;}//开始while(1){int res = tcp_server.StartCreateThread();if(res == 0){break;}} //关闭tcp_server.CloseServerSock();return 0;
}
第四:结尾
线程的这个,只是简单的开辟一个线程进行回声服务端的编写,理论上还需要其他的技术,我也正在学习,这篇只是展示怎么写,写的也不是很好,应该有很多的bug。
还是那句话,如果错误,希望海涵,初学者,希望可以帮到各位。
需要源码的,可以留下qq号,我可以邮箱发给你。
Linux下基于C++11的socket网络编程(线程版本)相关推荐
- Linux下基于C/C++的Socket编程基础
什么是Socket Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序.要学Internet上的TCP/IP网络编程, ...
- linux下的C语言开发(网络编程)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 不管在Windows平台下面还是在Linux平台下面,网络编程都是少不了的.在互联网发达的今天 ...
- linux下基于c++使用opencv的cpu和gpu版本提取tvl1光流
使用opencv c++版本提取tvl1光流 前言 Gpu版本 cpu版本 配置文件及运行 前言 在计算机视觉中,光流可以用来反映视频中的信息,在行为识别,跟踪,视频分割等任务中都使用.对光流不了解的 ...
- 流式套接字:基于TCP协议的Socket网络编程(案例2)
案例:在案例1的基础上实现一个服务器对应多个客户端(多线程),且获得每个客户端的IP. 线程代码: package com.yh.mySocket;import java.io.BufferedRea ...
- Python Socket网络编程(一)初识Socket和Socket初步使用
目录 前言 网络编程 实质 IP地址和端口 数据传输协议 协议 Socket 概念 套接字 socket对象方法 初步使用 功能 源码 运行结果 结语 前言 本系列博客是笔者学习Python Sock ...
- Python Socket网络编程(二)局域网内和局域网与广域网的持续通信
目录 前言 IP地址 简介 公有IP 私有IP 局域网之间网络通信 前提 功能描述 源码 运行结果 局域网与广域网网络通信 前提 源码 结语 前言 本系列博客是笔者学习Python Socket的过程 ...
- 基于Linux的socket网络编程项目——游侠手机商城
基于Linux的socket网络编程项目--游侠手机商城 一.项目说明 二.项目使用的技术 三.客户端搭建 四.服务器端搭建 一.项目说明 本项目是一个仿真手机商城类系统,基本功能: 登录界面功能:用 ...
- Linux下基于TCP的简易文件传输(socket编程)
Linux下基于TCP的简易文件传输(socket编程) OSI和TCP/IP: 关于TCP/IP协议 关于TCP协议 TCP编程的一般步骤[^2] TCP文件传输实现 功能概述 服务器编程 客户端编 ...
- linux下C语言socket网络编程简例
转自博文:http://blog.csdn.net/kikilizhm/article/details/7858405 在练习写网络编程时,该例给了我帮助,在写服务器时,我把while逻辑位置想法错了 ...
最新文章
- Java中的随机数生成器:Random,ThreadLocalRandom,SecureRandom
- [原创]Silverlight与PostgreSQL数据库的互操作(CURD完全解析)
- 构建javaweb项目
- wifi共享大师电脑版_Wifi分析助手PC版-Wifi分析助手电脑版下载 v7.2.2-
- 超长数列中n个整数排序C++代码实现
- hadoop2.0以后不需要借助cywin运行在Windows上
- tinymce vue 部分工具不显示_tinymce-vue使用问题及解决记录
- 绝了,66道并发多线程面试题汇总
- 实验四+040+薛龚
- 刷卡读取信息自动录入表格_人事自动化管理系统.xls
- 网站html页面显示404错误,网站怎样设置404错误页面
- 树莓派PI2编译天猫魔盘驱动,附编译好ko文件
- 9针串口的RS232、RS485、RS422引脚定义
- 桑格测序服务市场现状及未来发展趋势
- WDS桥接和WDS中继的区别
- 实用又方便电脑快捷键
- MySQL DATE_SUB() -- 从日期减去指定的时间间隔
- 高中数学必修2试题:直线平面平行的判定及其性质
- 忘记本地mysql密码_本地MySQL密码忘了,怎么找回?
- Linux系统配置网卡ip地址
热门文章
- matlab弹奏旋律(发声)笔记
- 随机数字信号处理实验报告三——Levinson和Burg递推法MATLAB实现
- 云直播丁云鹏:最可怕的,是你低估生活的残酷
- 图论——最短路径之渡河问题
- 【Unity3D】AR游戏制作 - Sikuto's Farm
- 【Android】多语言适配:语言、名称、与资源对应关系
- 简单易学的win10安装教程,值得收藏
- svg元素 标签增加、移除class名
- Linux C语言 pthread_cond_wait()、pthread_cond_timedwait()函数(不允许cond被唤醒时产生竞争,所以需要和互斥锁搭配)
- Testin云测试平台