Linux——网络通信TCP通信常用的接口和tcp服务demo

这篇具有很好参考价值的文章主要介绍了Linux——网络通信TCP通信常用的接口和tcp服务demo。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

TCP通信所需要的套接字

socket()

socket()函数主要作用是返回一个描述符,他的作用就是打开一个网络通讯端口,返回的这个描述符其实就可以理解为一个文件描述符,tcp在通讯的时候是会开辟一个缓存空间的,我们发送和读取消息可以理解为在这个缓存空间中进行的。因此这里我们可以知道我们可以直接用write和read函数进行消息的写入和读取,如果socket()调用出错则返回-1;
对于IPv4, family参数指定为AF_INET;
对于TCP协议,type参数指定为SOCK_STREAM, 表示面向流的传输协议
protocol参数的介绍从略,指定为0即可。
代码如下以ipv4协议为例

int socketfd=socket(AF_INET,SOCK_STREAM,0)

bind()

bind()函数的作用是为了让socket返回的描述符与端口号进行绑定在bind函数之前我们还需要做一个工作就是将我们的信息存入一个结构体sockaddr_in中,struct sockaddr *是一个通用指针类型,myaddr参数实际上可以接受多种协议的sockaddr结构体,而它们的长度各不相同,所以需要第三个参数addrlen指定结构体的长度
Linux——网络通信TCP通信常用的接口和tcp服务demo,linux,linux,tcp/ip,网络
我们的程序中对myaddr参数是这样初始化的:

sockaddr_in local;
bzero(&local, sizeof(local));//将整个结构体清0
local.sin_port = htons(port_);//porty_是我们的端口号这里是将这个端口号转化为网络序列一般我们的端口号都设置为8000以上
local.sin_family = AF_INET;//设置地址类型为AF_INET
inet_aton(ip_.c_str(), &(local.sin_addr));//网络地址为INADDR_ANY, 这个宏表示本地的任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP 地址, 这样设置可以在所有的IP地址上监听,直到与某个客户端建立了连接时才确定下来到底用哪个IP 地址;

listen()

Linux——网络通信TCP通信常用的接口和tcp服务demo,linux,linux,tcp/ip,网络
liasten函数生命socketfd正处于监听状态并且最多可以允许backlog个客户端处于连接等待状态如果收到更多连接请求就会忽略
listen成功返回0 失败则是-1

accept

Linux——网络通信TCP通信常用的接口和tcp服务demo,linux,linux,tcp/ip,网络
accept函数是为了接受来自客户端的连接请求的函数它是在三次握手之后发挥作用,这里也会有一些问题比如说accept发挥作用的时候此时并没有客户发送连接请求该怎么办呢?这里会陷入阻塞等待的状态也就是一直等到有连接请求为止。

connect()

Linux——网络通信TCP通信常用的接口和tcp服务demo,linux,linux,tcp/ip,网络
客户端需要调用connect()连接服务器;
connect和bind的参数形式一致, 区别在于bind的参数是自己的地址, 而connect的参数是对方的地址;
connect()成功返回0,出错返回-1

封装TCP socket

tcp_socket.hpp

#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <cassert>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
#define CHECK_RET(exp) if (!(exp)) {\
 return false;\
}
class TcpSocket {
public:
 TcpSocket() : fd_(-1) { }
 TcpSocket(int fd) : fd_(fd) { }
 bool Socket() {
 fd_ = socket(AF_INET, SOCK_STREAM, 0);
 if (fd_ < 0) {
 perror("socket");
 return false;
 }
 printf("open fd = %d\n", fd_);
 return true;
 }
 bool Close() const {
 close(fd_);
 printf("close fd = %d\n", fd_);
 return true;
 }
 bool Bind(const std::string& ip, uint16_t port) const {
 sockaddr_in addr;
 addr.sin_family = AF_INET;
 addr.sin_addr.s_addr = inet_addr(ip.c_str());
 addr.sin_port = htons(port);
 int ret = bind(fd_, (sockaddr*)&addr, sizeof(addr));
 if (ret < 0) {
 perror("bind");
 return false;
 }
 return true;
 }
 bool Listen(int num) const {
 int ret = listen(fd_, num);
 if (ret < 0) {
 perror("listen");
 return false;
 }
 return true;
 }
 bool Accept(TcpSocket* peer, std::string* ip = NULL, uint16_t* port = NULL) const {
 sockaddr_in peer_addr;
 socklen_t len = sizeof(peer_addr);
 int new_sock = accept(fd_, (sockaddr*)&peer_addr, &len);
 if (new_sock < 0) {
 perror("accept");
 return false;
 }
 printf("accept fd = %d\n", new_sock);
 peer->fd_ = new_sock;
 if (ip != NULL) {
 *ip = inet_ntoa(peer_addr.sin_addr);
 }
 if (port != NULL) {
 *port = ntohs(peer_addr.sin_port);
 }
 return true;
 }
 bool Recv(std::string* buf) const {
 buf->clear();
 char tmp[1024 * 10] = {0};
 // [注意!] 这里的读并不算很严谨, 因为一次 recv 并不能保证把所有的数据都全部读完
 // 参考 man 手册 MSG_WAITALL 节. 
 ssize_t read_size = recv(fd_, tmp, sizeof(tmp), 0);
 if (read_size < 0) {
 perror("recv");
 return false;
 }
 if (read_size == 0) {
 return false;
 }
 buf->assign(tmp, read_size);
 return true;
 }
 bool Send(const std::string& buf) const {
 ssize_t write_size = send(fd_, buf.data(), buf.size(), 0);
 if (write_size < 0) {
 perror("send");
 return false;
 }
 return true;
 }
 bool Connect(const std::string& ip, uint16_t port) const {
 sockaddr_in addr;
 addr.sin_family = AF_INET;
 addr.sin_addr.s_addr = inet_addr(ip.c_str());
 addr.sin_port = htons(port);
 int ret = connect(fd_, (sockaddr*)&addr, sizeof(addr));
 if (ret < 0) {
 perror("connect");
 return false;
 }
 return true;
 }
 int GetFd() const {
 return fd_;
 }
 private:
 int fd_;
};

tcp_server.hpp文章来源地址https://www.toymoban.com/news/detail-831653.html

#pragma once
#include <functional>
#include "tcp_socket.hpp"
typedef std::function<void (const std::string& req, std::string* resp)> Handler;
class TcpServer {
public:
 TcpServer(const std::string& ip, uint16_t port) : ip_(ip), port_(port) {
 }
 bool Start(Handler handler) {
 // 1. 创建 socket;
 CHECK_RET(listen_sock_.Socket());
 // 2. 绑定端口号
 CHECK_RET(listen_sock_.Bind(ip_, port_));
 // 3. 进行监听
 CHECK_RET(listen_sock_.Listen(5));
 // 4. 进入事件循环
 for (;;) {
 // 5. 进行 accept
 TcpSocket new_sock;
 std::string ip;
 uint16_t port = 0;
 if (!listen_sock_.Accept(&new_sock, &ip, &port)) {
 continue;
 }
 printf("[client %s:%d] connect!\n", ip.c_str(), port);
 // 6. 进行循环读写
 for (;;) {
 std::string req;
 // 7. 读取请求. 读取失败则结束循环
 bool ret = new_sock.Recv(&req);
 if (!ret) {
 printf("[client %s:%d] disconnect!\n", ip.c_str(), port);
 // [注意!] 需要关闭 socket
 new_sock.Close();
 break;
 }
 // 8. 计算响应
 std::string resp;
 handler(req, &resp);
 // 9. 写回响应
 new_sock.Send(resp);
printf("[%s:%d] req: %s, resp: %s\n", ip.c_str(), port,
 req.c_str(), resp.c_str());
 }
 }
 return true;
 }
private:
 TcpSocket listen_sock_;
 std::string ip_;
 uint64_t port_;
};
我们开开心心的在一起

到了这里,关于Linux——网络通信TCP通信常用的接口和tcp服务demo的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Unity】Socket网络通信(TCP) - 最基础的C#服务端通信流程

    我这里新建了一个C#控制台项目来写服务端代码。 下面是基于C# Socket的最基础服务端通信流程: 创建服务端Socket对象 绑定IP地址和端口 设置最大监听客户端数量 等待客户端连接 收发消息 释放连接 基于上面流程就能实现一个最简单并且能和客户端通信的服务器程序,每个步

    2023年04月16日
    浏览(51)
  • 网络通信(11)-C#TCP服务端封装帮助类实例

    本文使用Socket在C#语言环境下完成TCP服务端封装帮助类的实例。 实例完成的功能: 服务器能够连接多个客户端显示在列表中,实现实时刷新。 服务器接收客户端的字符串数据。 选中列表中的客户端发送字符串数据。 在VS中创建C# Winform项目,编辑界面,如下: UI文件

    2024年02月02日
    浏览(35)
  • C++网络通信实例(TCP/IP协议,包括服务端与客户端通信)

    创作不易 觉得有帮助请点赞关注收藏 TCP/IP是当下网络协议栈中的主流协议 TCP属于传输层的协议  可靠传输 包括经典的三次握手等等 IP协议是网络层协议 尽全力传输但不可靠 学过计算机网络的同学们对这个应该比较熟悉 以下是使用C++进行网络通信的实例  服务端 主要使用

    2024年02月14日
    浏览(44)
  • UE4 TCP通信 (UE客户端与网络调试助手服务端、python服务端通信)

    目录 一、使用UE4建立TCP客户端 二、使用网络调试助手建立服务端 三、基于网络调试助手的服务端与UE客户端通信 四、基于python的TCP服务端与UE客户端通信  1.在虚幻商城中搜索socket来下载TCP Socket Plugin插件   2.安装到引擎,目前支持的版本是4.22-4.27和5.0  点击安装 大约30M 

    2024年01月16日
    浏览(41)
  • linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手

    Tcp通信模拟实现与Udp通信模拟实现的区别不大,一个是面向字节流,一个是面向数据报;udp协议下拿到的数据可以直接发送,tcp协议下需要创建链接,用文件描述符完成数据的读写 1.1.1 接口认识 1.1.1.1 listen:监听socket 1.1.1.2 accept:获取连接 通信就用accept返回的文件描述符,

    2024年02月06日
    浏览(46)
  • Linux网络编程——C++实现进程间TCP/IP通信

    地址接口 1、通用地址接口 共16字节 = 2字节地址类型 + 14字节地址数据 2、自定义地址接口 地址转换 1、需要将点分字符串ip转化为程序ip,使用inet_addr函数: 2、字节序转换 地址接口配置中的端口需要字节序转换,网络规定使用大端字节序。 地址接口配置 1、socket:创建套接

    2024年02月20日
    浏览(45)
  • Socket网络编程(TCP/IP)实现服务器/客户端通信。

    一.前言 回顾之前进程间通信(无名管道,有名管道,消息队列,共享内存,信号,信号量),都是在同一主机由内核来完成的通信。 那不同主机间该怎么通信呢? 可以使用Socket编程来实现。 Socket编程可以通过网络来实现实现不同主机之间的通讯。 二.Socket编程的网络模型如

    2024年02月08日
    浏览(74)
  • Linux中建立TCP网络通信,代码运行异常,[Errno 111] Connection refused

    代码如下: 报错信息: 原因: 直接理解报错的意思就是:链接失败。 Linux端作为客户端,Windows端作为服务端,排查服务端的本地地址,发现有误,所以引起链接失败。

    2024年02月15日
    浏览(31)
  • C++网络编程 TCP套接字基础知识,利用TCP套接字实现客户端-服务端通信

    流式套接字编程针对TCP协议通信,即是面向对象的通信,分为服务端和客户端两部分。 1)加载套接字库( 使用函数WSAStartup() ),创建套接字( 使用socket() ) 2)绑定套接字到一个IP地址和一个端口上( 使用函数bind() ) 3)将套接字设置为监听模式等待连接请求( 使用函数

    2024年02月03日
    浏览(43)
  • 【网络原理】使用Java基于TCP搭建简单客户端与服务器通信

    TCP服务器与客户端的搭建需要借助以下API ServerSocket 是创建TCP服务端Socket的API。 ServerSocket 构造方法 : 方法签名 方法说明 ServerSocket(int port) 创建一个服务端流套接字Socket,并绑定到指定端口 ServerSocket 方法: 方法签名 方法说明 Socket accept() 开始监听指定端口(创建时绑定的端

    2024年03月12日
    浏览(72)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包