tcp网络编程(基础)

目录

一.编程前的一些基础

二.tcp网络编程

1.一个服务器只能有一个客户端连接(下面代码)

Socket.hpp

TcpServer.hpp

 TcpServerMain.cc

TcpClientMain.cc

2.一个服务器可以有多个客户端连接(多线程)


看这篇文章前,先把有关udp和一些网络基础看了(最好敲一下代码)

网络基础1-CSDN博客

一.编程前的一些基础

1.tcp是面向连接的,面向字节流的,在通信前要先建立连接(将服务端设置为监听状态(listen),服务端等待连接的到来(accept),客户端主动建立连接(connect),建立连接后就可以通信(send,recv)了)

二.tcp网络编程

1.一个服务器只能有一个客户端连接(下面代码)

Socket.hpp

#pragma once#include<iostream>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include<cstring>
#include<string>
#include <unistd.h>#define Convert(addr) ((struct sockaddr*)addr)enum
{SocketError = 1,BindError,ListenError,
};const static int defaultbackflag = 5;
const int defaultsockfd = -1;//简单解释下:Socket.hpp用了继承,多态的知识
//我们将创建socket,bind, listen, accept, connect等方法都单独封装起来class Socket
{
public:Socket(){}~Socket(){}virtual void CreateSocket() = 0; //创建socket套接字virtual void BindSocket(uint16_t port) = 0; //绑定套接字virtual void ListenSocket(int backflag = defaultbackflag) = 0; //将服务端设置为监听状态virtual Socket* AcceptConnection(std::string *peerip, uint16_t *peerport) = 0; //服务端接收客户端发来的连接请求virtual bool ConnectServer(std::string& serverip, uint16_t serverport) = 0; //客户端准备连接服务端virtual int GetSockfd() = 0; //获取sockfdvirtual void SetSockfd(int sockfd) = 0;virtual void CloseSockfd() = 0; //关闭文件描述符
public://将服务端设置为监听状态 //tcpserver.hpp调用void BuildListenSocketMethod(uint16_t port, int backflag = defaultbackflag){CreateSocket();BindSocket(port);ListenSocket(backflag);}//客户端去连接服务端  //tcpclient.hpp调用bool BuildConnectSocketMethod(std::string& serverip, uint16_t serverport){CreateSocket();return ConnectServer(serverip, serverport);}void BuildNormalSocketMethod(int sockfd){SetSockfd(sockfd);}
};//继承并将具体方法实现
class TcpSocket : public Socket
{
public:TcpSocket(int sockfd = defaultsockfd):_sockfd(sockfd){}void CreateSocket() override{//创建socket套接字//tcp用SOCK_STREAM,_sockfd = socket(AF_INET, SOCK_STREAM, 0);if(_sockfd < 0)//失败{exit(SocketError);}}void BindSocket(uint16_t port) override{//方法同udpstruct sockaddr_in local;local.sin_family = AF_INET;local.sin_port = htons(port);local.sin_addr.s_addr = INADDR_ANY;int n = bind(_sockfd, Convert(&local), sizeof(local)); //绑定本机socketif(n != 0) exit(BindError);}void ListenSocket(int backflag = defaultbackflag) override{//设置服务端为监听状态int n = listen(_sockfd, backflag);if(n != 0) exit(ListenError);}//peerip,peerport是输出型参数,目的是获取有关client的一些信息,并为我们所用Socket* AcceptConnection(std::string* peerip, uint16_t* peerport) override{//client的一些信息struct sockaddr_in peer;socklen_t len = sizeof(peer);//服务端获取客户端的connect请求,进行连接(此函数阻塞等待)//accept成功会返回一个新的文件描述符(>0),我们使用新的文件描述符进行通信int newsockfd = ::accept(_sockfd, Convert(&peer), &len);if(newsockfd < 0) return nullptr;*peerip = inet_ntoa(peer.sin_addr);*peerport = ntohs(peer.sin_port);Socket* s = new TcpSocket(newsockfd);return s;}bool ConnectServer(std::string& serverip, uint16_t serverport) override{//客户端发送连接请求struct sockaddr_in server;memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport);inet_pton(AF_INET, serverip.c_str(), &server.sin_addr); //更安全//或者server.sin_addr.s_addr = inet_addr(serverip.c_str());//失败-1,并且我们发起连接时,client会被os自动地进行bind,我们不需要自己调用bind函数int n = ::connect(_sockfd, Convert(&server), sizeof(server));if(n == 0) return true;else return false;}int GetSockfd() override{return _sockfd;}void SetSockfd(int sockfd) override{_sockfd = sockfd;}void CloseSockfd() override  //关闭文件描述符{if(_sockfd > defaultsockfd) {close(_sockfd);}}private:int _sockfd;
};

TcpServer.hpp

#pragma once#include<iostream>
#include"Socket.hpp"class TcpServer
{
public:TcpServer(uint16_t port) :_port(port), _listensocket(new TcpSocket()){_listensocket->BuildListenSocketMethod(_port, defaultbackflag); //设置为监听状态}void Loop(){char bufferin[1024];std::string peerip;uint16_t peerport;Socket* s = _listensocket->AcceptConnection(&peerip, &peerport); //服务端接收客户端发来的连接请求if(s == nullptr) exit(0);std::cout << "accept success" << std::endl;while(true) //接收client发的信息{ssize_t n = recv(s->GetSockfd(), bufferin, sizeof(bufferin)-1, 0); //接收client发送的信息//ssize_t n = (s->GetSockfd(), bufferin, sizeof(bufferin)-1);if(n > 0){bufferin[n] = 0;std::string ret;ret += peerip;ret += " ";ret += std::to_string(peerport);std::cout << ret << " " << "client say#" << bufferin << std::endl;}else{break;}}}~TcpServer(){delete _listensocket;}
private:int _port;Socket* _listensocket;
};

 TcpServerMain.cc

#include<iostream>
#include<memory>
#include"TcpServer.hpp"//./tcpserver 8888
int main(int argc, char* argv[])
{if(argc != 2){std::cout << "Usage:" << "./tcpserver " << "serverport" << std::endl;}uint16_t localport = std::stoi(argv[1]);std::unique_ptr<TcpServer> svr(new TcpServer(localport));svr->Loop();return 0;
}

TcpClientMain.cc


#include<iostream>
#include "Socket.hpp"
//./tcpclient 127.0.0.1 8888
int main(int argc, char* argv[])
{if(argc != 3){std::cout << "Usage:" << "./tcpclient " << "serverip serverport" << std::endl;}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);Socket* s = new TcpSocket();if(!s->BuildConnectSocketMethod(serverip, serverport)) //向服务端申请建立连接{std::cerr << "connect " << serverip << ":" << serverport << " failed" << std::endl;}std::cout << "connect " << serverip << ":" << serverport << " success" << std::endl;std::string buffer;while(true)//发信息给服务端{std::getline(std::cin, buffer);std::cout << "Enter:" << std::endl;ssize_t n = send(s->GetSockfd(), buffer.c_str(), buffer.size(), 0); //向服务端发送信息//ssize_t n = write(s->GetSockfd(), buffer.c_str(), buffer.size());if(n < 0){break;}}s->CloseSockfd();return 0;
}

2.一个服务器可以有多个客户端连接(多线程)

server端创建多个线程,每个线程与不同的client端建立连接。

tcp网络编程——2-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/1552.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自定义注解+AOP实现日志记录

定义日志表结构 CREATE TABLE sys_oper_log (id bigint NOT NULL AUTO_INCREMENT COMMENT 日志主键,title varchar(50) DEFAULT COMMENT 模块标题,business_type varchar(20) DEFAULT 0 COMMENT 业务类型&#xff08;0其它 1新增 2修改 3删除&#xff09;,method varchar(100…

9.MMD 基础内容总结及制作成品流程

前期准备 1. 导入场景和模型 在左上角菜单栏&#xff0c;显示里将编辑模型时保持相机和光照勾选上&#xff0c;有助于后期调色 将抗锯齿和各向异性过滤勾掉&#xff0c;可以节省资源&#xff0c;避免bug 在分辨率设定窗口&#xff0c;可以调整分辨率 3840x2160 4k分辨率 1…

【python】图形用户界面学习之tkinter

认识tkinter Tkinter是Python中内置的图形用户界面&#xff08;GUI&#xff09;库。它是Tk GUI工具包的接口&#xff0c;可以创建和管理窗口、按钮、标签、文本框等各种GUI组件&#xff0c;并与用户交互。 使用Tkinter&#xff0c;可以创建各种GUI应用程序&#xff0c;如桌面…

QT Webengine开发过程报错qml: Render process exited with code 159 (killed)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、解决方法二、补充说明总结 前言 基于QT的Webengine开发过程中&#xff0c;QT的官方示例quicknanobrowser也无法成功运行&#xff0c;程序运行后&#xff0…

git的学习

设置用户&#xff08;目的在于可以在远端看到是谁提交了内容&#xff0c;更方便公司的管理&#xff09; 1、设置全局用户&#xff08;在家路径下创建用户&#xff0c;每个项目都用这一个用户&#xff09;>: git config --global user.name manba >: git config --global …

《AI聊天类工具之八——​ 小悟空》

一.简介 官网:小悟空 小悟空是一款集智能对话和辅助推荐功能于一体的强大工具集。它为用户提供了创作生成、学习提升、工作职场、专业咨询、虚拟角色和休闲娱乐等二十余个类别的智能服务,以满足用户在工作、生活和娱乐各方面的需求。 在创作生成方面,小悟空可以帮助用户进…

使用Go语言和chromedp库下载Instagram图片:简易指南

摘要/导言 本文将介绍如何使用Go语言配合chromedp库来下载Instagram上的图片。我们将通过一个简单的示例来展示整个过程&#xff0c;包括如何设置爬虫代理IP以绕过网络限制。 背景/引言 在数据采集和自动化测试领域&#xff0c;Go语言以其出色的执行效率、简洁的语法和卓越的…

【科学研究】那些考进精英大学的农家子弟们

::: block-1 “时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验&#xff0c;帮助大家尽早适应研究生生活&#xff0c;尽快了解科研的本质。祝一切顺利&#xff01;—…

智能化转型的得力助手:山海鲸智慧工厂解决方案详解

在数字化浪潮席卷全球的今天&#xff0c;工业领域正迎来一场前所未有的智能化变革。作为这一变革的领军者&#xff0c;山海鲸智慧工厂解决方案以其前瞻性的技术理念和创新的解决方案&#xff0c;为工业发展注入了强大的动力。 山海鲸智慧工厂解决方案的核心在于其高度的集成性…

uniapp读取(获取)缓存中的对象值(微信小程序)

文章目录 问题描述解决方案存值取值 问题描述 大家好&#xff01;我是夏小花&#xff0c;今天是2024年4月24日|农历三月十六&#xff0c;在我们日常开发中&#xff0c;做小程序可能会往缓存中存值或者是存对象&#xff0c;今天这篇博客文章主要是讲如何在微信小程序如何读取缓存…

Windows Server 2012 R2 中 IIS 8.5 安装证书

文章目录 前言一、获取服务器证书二、证书格式转换二、IIS8安装证书1.Win R 键打开运行窗口 → 输入【inetmgr】→ 点击【确定】2.打开【IIS管理器】→ 点击计算机名称 → 双击打开【服务器证书】3.点击【导入】4.选择证书文件 → 输入密码 → 点击【确定】5.选择要使用证书的…

14. Spring AOP(二)实现原理

源码位置&#xff1a;spring_aop 上一篇文章中我们主要学习了AOP的思想和Spring AOP使用&#xff0c;本文讲的是Spring是如何实现AOP的&#xff0c;Spring AOP是基于动态代理来实现AOP的&#xff0c;在将动态代理之前先来了解一下什么是代理模式。 1. 代理模式 在现实中就有许…

深度学习transformer架构详细详解

一、transformer的贡献 transformer架构的贡献&#xff1a;该架构只使用自注意力机制&#xff0c;没有使用RNN或卷积网络。且可以实现并行计算&#xff0c;加快模型训练速度。 &#xff08;将所有的循环层全部换成&#xff1a;multi-headed self-attention&#xff09; 二、t…

VisualStudio2019和2022开发Winform项目用到Devexpress组件报错不能正确加载的解决办法

1.报错1 问题简单描述&#xff1a;DevExpress.Utils.ImageCollectionStreamer 无法强制转换为 DevExpress.Utils.ImageCollectionStreamer。 原因分析&#xff1a;原项目某个组件使用的是 DevExpresss.XtraBars.v15.1版本&#xff0c;直接引用扩展控件改成引用v20.2。 解决办法…

负载均衡集群——Nginx

目录 1.Nginx反向代理实战 2.Nginx 反向代理和负载均衡实践 实验操作步骤 步骤 1 Nginx1 和 Nginx2 配置 步骤2 测试资源是否可用 步骤 3 安装和配置 Nginx 代理 步骤 4 代理服务器配置检测 步骤 5 在 Nginx1 和 Nginx2 配置虚拟主机 步骤 6 将虚拟主机添加入后端主机组…

Let’s Encrypt 申请免费https证书(snapd安装)

Let’s Encrypt 最近给域名安装免费的https证书 Let’s Encrypt&#xff0c;发现跟之前的安装方式不太一样&#xff0c;这里记录一下安装过程 https://certbot.eff.org/instructions?wsnginx&oscentosrhel7 https://eff-certbot.readthedocs.io/en/latest/using.html#ng…

BMR:基于Boostrapping多视图的虚假新闻检测

一、概述 文章提出了三种视图信息来表示一篇新闻&#xff1a;文本、图像结构、图像语义。然后设计了改进的多门混合专家系统&#xff08;iMMoE&#xff09;来进行信息融合。保留单模态信息来保证特征对新闻的保真性&#xff0c;增加的多模态信息能保证不同模态的一致性&#xf…

【技术】Spring Boot 将 Word 转换为 PDF 2.0 版本

之前写过一篇 Spring Boot 将 Word 转换为 PDF 的文章&#xff0c;但是有评论说导入依赖有问题&#xff0c;还存在依赖冲突的问题。索性再来一个完整版的代码&#xff0c;之前的完整版代码找不到了&#xff0c;又重新整理了一下&#xff0c;依赖导入和之前不太一样&#xff0c;…

【KingSCADA】通过地址引用和弹窗模板实现设备控制

当相同的设备过多时&#xff0c;要做很多相同的弹窗&#xff0c;这种情况下可以通过地址引用和弹窗模板实现设备控制。 1.变量创建 2.画面开发 以阀门控制为例&#xff0c;只需要做一个阀门控制界面模板 3.地址引用 # 4.实现效果

eCognition 样本标注与导出

目录 一、可导出shp的样本标注方式 1、选择样本 2、导出样本shp 3、附录:转成样本用于训练 二、只能导出tif,不可导出shp 1、打开样本工具栏 2、选择样本 3、导出标注