TCP服务器—实现数据通信

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

目录

前言

1.接口介绍

2.编写服务器

3.编写客户端

4.编译链接

5.测试

6.总结


前言

        今天我们要介绍的是使用TCP协议实现数据通信,相比于之前写的UDP服务器实现数据信,在主体逻辑上并没有差别。客户端向服务器发送信息,服务器接受信息并回显,因为UDP是面向数据报,而TCP是面向连接的,所以在实现的时候接口上会有一些差别,下面,我们具体来看看UDP和TCP在编码的实现上有什么不同。

1.接口介绍

因为TCP是面向连接的,所以服务器创建完套接字,然后绑定成功后,将套接字设置为监听套接字

服务器启动之后,首先需要根据监听套接字建立连接,建立连接成功后返回一个新的文件描述符,后续的通信都是按照这个新的文件描述符按照读写文件的形式进行读写数据。

对于客户端来说创建完套接字之后,客户端启动之后首先需要建立连接

listen():设置sock为监听状态

 #include <sys/types.h>       
 #include <sys/socket.h>
 int listen(int sockfd, int backlog);

sockfd:创建套接字的返回值

backlog:底层全连接队列的长度

accept():服务端建立连接

#include <sys/types.h>         
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

sockfd:监听套接字

struct sockaddr* addr:输出型参数,可以获取服务端的IP地址和port端口号

socklen_t* addrlen:结构体的大小

返回值:返回一个新打开的文件描述符

connect():客户端建立连接

#include <sys/types.h>        
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

sockfd:创建套接字返回值

struct sockaddr* addr:输出型参数,用来填写需要访问的服务端的IP地址和port端口号

socklen_t addrlen:结构体的大小

2.编写服务器

tcpServer.hpp

#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "log.hpp"
namespace server
{
    using namespace std;
    enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR
    };
    static const uint16_t gport = 8080;
    static const int gback = 5;
    class TcpServer
    {
    public:
        TcpServer(const uint16_t &port = gport)
            : _port(gport), _sock(-1)
        {}
        void InitServer()
        {
            _sock = socket(AF_INET, SOCK_STREAM, 0);
            if (_sock < 0)
            {
                logMessage(FATAL, "create socket error");
                exit(SOCKET_ERR);
            }
            logMessage(NORMAL, "create socket success");
            // 绑定:
            struct sockaddr_in local;
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;
            if (bind(_sock, (struct sockaddr *)&local, sizeof(local)) < 0)
            {
                logMessage(FATAL, "bind socket error");
                exit(BIND_ERR);
            }
            logMessage(NORMAL, "bind socket success");
            // 设置sock为监听状态:
            if (listen(_sock, gback) < 0)
            {
                logMessage(FATAL, "listen socket error");
                exit(LISTEN_ERR);
            }
            logMessage(NORMAL, "listen socket success");
        }
        void start()
        {
            for (;;)
            {
                // 建立连接:
                struct sockaddr_in peer;
                socklen_t len = sizeof(peer);
                int sock = accept(_sock, (struct sockaddr *)&peer, &len); 
                if (sock < 0)
                {
                    logMessage(ERROR, "accept error, next");
                    continue;
                }
                logMessage(NORMAL, "accept a new link success");
                std::cout << "sock: " << sock << std::endl;
                //未来通信全部用sock,面向字节流的,后续全部都是文件操作:
                serviceIO(sock);
                close(sock);
            }
        }
        void serviceIO(int sock)
        {
            char buffer[1024];
            while(true)
            {
                ssize_t n = read(sock,buffer,sizeof(buffer)-1);
                if(n > 0)
                {
                    buffer[n] = 0;
                    cout << "recvice message: " << buffer << endl;
                    string outbuffer = buffer;
                    outbuffer += "[server echo]";
                    write(sock,outbuffer.c_str(),outbuffer.size());
                }
                else if(n == 0)
                {
                    // 代表client退出
                    logMessage(NORMAL, "client quit, me too!");
                    break;
                }
            }
        }
        ~TcpServer()
        {}
    private:
        int _sock;
        uint16_t _port;
    };
}

tcpServer.cc:启动服务器

#include"tcpServer.hpp"
#include<memory>
using namespace server;
static void Usage(string proc)
{
    cout << "\nUsage:\n\t" << proc << " local_port\n\n";
}
int main(int argc,char* argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);
    unique_ptr<TcpServer> tcs(new TcpServer(port));
    tcs->InitServer();
    tcs->start();
    return 0;
}

3.编写客户端

tcpClient.hpp

#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

namespace client
{
    using namespace std;
    class TcpClient
    {
    public:
        TcpClient(const string& serverip,const uint16_t port)
        :_serverip(serverip),_port(port),_sock(-1)
        {}
        void InitClient()
        {
            _sock = socket(AF_INET,SOCK_STREAM,0);
            if(_sock < 0)
            {
                cerr << "create sock fail" << endl;
                exit(-1);
            }
        }
        void start()
        {
            //建立连接:
            struct sockaddr_in server;
            server.sin_family = AF_INET;
            server.sin_port = htons(_port);
            server.sin_addr.s_addr = inet_addr(_serverip.c_str());
            if(connect(_sock,(struct sockaddr*)&server,sizeof(server)) != 0)
            {
                cerr << "connect fail" << endl;
            }
            else
            {
                string message;
                while(true)
                {
                    cout << "Please Enter: ";
                    getline(cin,message);
                    write(_sock,message.c_str(),message.size());
                    char buffer[1024];
                    int n = read(_sock,buffer,sizeof(buffer)-1);
                    if(n > 0)
                    {
                        buffer[n] = 0;
                        cout << "Server回复: " << buffer << endl;
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
        ~TcpClient()
        {
            if(_sock >= 0)
                close(_sock);
        }
    private:
        string _serverip;
        uint16_t _port;
        int _sock;
    };
} // namespace client

tcpClient.cc:启动客户端

#include"tcpClient.hpp"
#include<memory>
using namespace client;
static void Usage(string proc)
{
    cout << "\nUsage:\n\t" << proc << " serverip serverport\n\n";
}
int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        Usage(argv[0]);
        exit(-1);
    }
    uint16_t port = atoi(argv[2]);
    string ip = argv[1];
    unique_ptr<TcpClient> tcc(new TcpClient(ip,port));
    tcc->InitClient();
    tcc->start();
    return 0;
}

4.编译链接

makefile:

.PHONY:all
all:tcpServer tcpClient
tcpServer:tcpServer.cc
	g++ -o $@ $^ -std=c++11
tcpClient:tcpClient.cc
	g++ -o $@ $^ -std=c++11
.PHONY:clean
clean:
	rm tcpServer tcpClient

5.测试

TCP服务器—实现数据通信,tcp/ip,服务器,网络

 如图所示,服务端和客户端可以完成正常的数据通信了。

6.总结

        TCP协议和UDP协议在数据通信的实现中,除了一些接口使用的不同之外,其实并没有太大的不同,在之前说的UDP是面向数据报的而TCP是面向字节流的,这些特性又是如何体现的呢?关于这个问题,博主将在后面的文章中会为大家继续进行介绍。不要错过哦!文章来源地址https://www.toymoban.com/news/detail-651937.html

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

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

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

相关文章

  • 【TCP服务器的演变过程】编写第一个TCP服务器:实现一对一的连接通信

    手把手教你从0开始编写TCP服务器程序,体验 开局一块砖,大厦全靠垒 。 为了避免篇幅过长使读者感到乏味,对【TCP服务器的开发】进行分阶段实现,一步步进行优化升级。 函数原型: 这个函数建立一个协议族、协议类型、协议编号的socket文件描述符。如果函数调用成功,

    2024年02月03日
    浏览(55)
  • TCP实现服务器和客户端通信

    目录 TCP介绍 代码实现 server(服务器端) 代码分析 client(客户端) 代码分析 结果展示 TCP (Transmission Control Protocol) 是一种面向连接的协议,用于在计算机网络中传输数据。TCP 可以确保数据的可靠传输,即使在网络环境不稳定的情况下也能够保证数据的完整性和顺序。以下是

    2024年02月15日
    浏览(62)
  • TCP通信实现客户端向服务器发送图片

    TCP通信: 1. TCP 协议通信交互流程: 具体的流程如下: (1)服务器根据地址类型(ipv4、ipv6)、socket 类型、协议创建 socket. (2)服务器为 socket 绑定 ip 地址和端口号。 (3)服务器 socket 监听端口号的请求,随时准备接受来自客户端的连接,此时服务器的 socket 处于关闭状态

    2024年02月13日
    浏览(59)
  • QT实现TCP通信(服务器与客户端搭建)

    创建一个QTcpServer类对象,该类对象就是一个服务器 调用listen函数将该对象设置为被动监听状态,监听时,可以监听指定的ip地址,也可以监听所有主机地址,可以通过指定端口号,也可以让服务器自动选择 当有客户端发来连接请求时,该服务器会自动发射一个newConnection信号

    2024年02月09日
    浏览(56)
  • Java实现TCP客户端和服务器端相互通信

    解决TCP客户端和服务器端通信读不到数据的问题  解决: 服务器端和客户端读完后加上client.shutdownInput(); 服务器端和客户端写完后加上client.shutdownOutput(); 服务器端代码: 客户端代码: 运行服务器端再运行客户端,在客户端中输入要发送的信息,回车 服务器收到信息,over

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

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

    2024年02月08日
    浏览(89)
  • 【Linux后端服务器开发】封装线程池实现TCP多线程通信

    目录 一、线程池模块 Thread.h LockGuard.h ThreadPool.h 二、任务模块模块 Task.h 三、日志模块 Log.h 四、守护进程模块 Deamon.h  五、TCP通信模块 Server.h Client.h server.cpp client.cpp 关于TCP通信协议的封装,此篇博客有详述: 【Linux后端服务器开发】TCP通信设计_命运on-9的博客-CSDN博客 线程池

    2024年02月16日
    浏览(45)
  • LabVIEW平台下的TCP数据通信实现

    LabVIEW是一种流行的图形化编程语言和开发环境,广泛应用于各种科学与工程领域。在LabVIEW中,可以使用TCP/IP协议实现网络通信,并通过TCP数据通信在不同设备之间传输数据。本文将介绍如何在LabVIEW平台下使用TCP/IP协议进行数据通信,并提供相关源代码示例。 TCP数据通信的基

    2024年02月03日
    浏览(35)
  • C#上位机基础学习_基于SOCKET实现与PLC服务器的TCP通信(一)

    测试软件: TIA PORTAL V15.1 S7-PLCSIM ADVANCED V3.0 Visual Studio 2019 如下图所示,打开S7-PLCSIM ADVANCED V3.0仿真软件,新键一个实例,设置仿真PLC的IP地址等参数,然后点击Start激活PLC, 如下图所示,激活PLC后,可以看到已经存在一个实例, 如下图所示,打开TIA PORTAL V15.1,新建一个项目,

    2023年04月15日
    浏览(46)
  • 网络通信(13)-C#TCP服务器和客户端同时在一个进程实现的实例

    有时项目需求中需要服务器和客户端同时在一个进程实现,一边需要现场接收多个客户端的数据,一边需要将数据汇总后发送给远程服务器。下面通过实例演示此项需求。 C#TCP服务器和客户端同时在一个进程实现的实例如下: 界面设计 UI文件代码

    2024年01月22日
    浏览(66)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包