一篇文章贯穿ACE各种发送接收组件 1.2版

TCP通信过程介绍

首先介绍一下socket通信的基本过程:这里先如果有两个家伙在通信,一个是S。还有一个叫C

(1)S打开port监听本地的port看看有没有人来连接;

(2)与此同一时候C试图去连接远程的S。连接的地址就是S的地址加上S监听的port号;

(3)S收到C的请求之后,建立连接,两方共同持有连接的通道。可互相发送/接收数据随意次。此时S和C无差别。

(4)当中一方断开连接,或者由于网络原因中断连接,还有一方也会关闭;

(5)此时通信过程结束;

整个步骤例如以下图所看到的

普通ACE通信类ACE_SOCK_*通信过程

ACE_SOCK_Connector  ACE_SOCK_Stream  ACE_SOCK_Acceptor完毕上面的通信过程:

TimerServer Edition 1.0  单次发送

两方建立连接》互发数据》关闭连接

Client:发送自己的签名给Server之后就准备接受Server发来的时间

Server:在连接建立后打印对方发来的签名。之后回复自己的时间给对方

Server  端 time_server_main.cpp

#include <ace/OS.h>
#include <ace/ACE.h>
#include <ace/Log_Msg.h>
#include <ace/SOCK_Acceptor.h>
#include "ace/Date_Time.h"

int main(int argc, char *argv[])
{
    ACE_INET_Addr addr(1500);
    ACE_SOCK_Acceptor server;
    ACE_SOCK_Stream stream;

    //启动监听
    if(server.open(addr)==-1)
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server启动监听本地端口1500失败\n")));
        return 1;
    }
    else
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server启动监听本地端口1500成功\n")));
    }

    char msg[1000];

    //建立链接
    if(server.accept(stream)!=-1)
    {
        ACE_INET_Addr raddr;
        stream.get_remote_addr(raddr);
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server建立链接成功 %s %d\n"),raddr.get_host_addr(),raddr.get_port_number()));

        if(stream.recv(msg,sizeof(msg)-1)==-1) // just call socket recv
            ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server recv failed\n")));
        else
        {
            ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server recv : %s\n"),msg));
            //get current time
            ACE_Date_Time date;
            sprintf(msg,"%ld-%ld-%ld %02ld:%02ld:%02ld:%02ld",date.year(),date.month(),date.day(),date.hour(),date.minute(),date.second(),date.microsec());
            //发送数据
            stream.send_n(msg,sizeof(msg));
            ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("发送当前时间%s至 %s %d\n"),msg,raddr.get_host_addr(),raddr.get_port_number()));
        }
    }
    else
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server建立链接失败\n")));
    }
    //关闭链接
    stream.close();
    ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server链接关闭了\n")));
    server.close();

    return 0;
}

Client端time_client_main.cpp

#include "ace/OS.h"
#include <ace/OS_main.h>
#include <ace/ACE.h>
#include <ace/Log_Msg.h>
#include <ace/SOCK_Connector.h>

int main(int argc, char *argv[])
{
    ACE_INET_Addr addr(1500,"127.0.0.1"); //remote address
    ACE_SOCK_Connector con; // connetor for socket client
    ACE_SOCK_Stream stream; // stream is for socket read/write

    //建立链接
    if(con.connect(stream,addr)==-1) //connect to remote address
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client建立链接失败\n")));
        return 1;
    }
    else
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client建立链接成功\n")));
    }

    const char msg[] = "Hello,ACE!";
    //发送数据
    stream.send_n(msg,sizeof(msg)); // send_n function send exactly n bytes

    char buffer[1024] = {0};
    //接收数据
    if(stream.recv(buffer,sizeof(buffer)-1)==-1) // just call socket recv
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client recv failed\n")));
        return 1;
    }
    else
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client recv:%s\n"),buffer));
    }

    //断开链接
    if (stream.close () == -1) //close the connection
    {
        ACE_ERROR ((LM_ERROR,ACE_TEXT ("Client close failed\n")));
        return 1;
    }
    else
    {
        ACE_ERROR ((LM_ERROR,ACE_TEXT ("Client close successed\n")));
    }
    return 0;
}

输出:

TimerServer Edition 2.0  多次发送

两方建立连接》互发数据》关闭连接

(1)Client:发送自己的签名给Server之后就准备接受Server发来的时间,此过程反复三次

(2)Server:在连接建立后打印对方发来的签名。之后回复自己的时间给对方。此过程直到对方关闭链接

Server  端 time_server_main.cpp

#include <ace/OS.h>
#include <ace/ACE.h>
#include <ace/Log_Msg.h>
#include <ace/SOCK_Acceptor.h>
#include "ace/Date_Time.h"

int main(int argc, char *argv[])
{
    ACE_INET_Addr addr(1500);
    ACE_SOCK_Acceptor server;
    ACE_SOCK_Stream stream;

    //启动监听
    if(server.open(addr)==-1)
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server启动监听本地端口1500失败\n")));
        return 1;
    }
    else
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server启动监听本地端口1500成功\n")));
    }

    char msg[1000];

    //建立链接
    if(server.accept(stream)!=-1)
    {
        ACE_INET_Addr raddr;
        stream.get_remote_addr(raddr);
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server建立链接成功 %s %d\n"),raddr.get_host_addr(),raddr.get_port_number()));

        while(stream.recv(msg,sizeof(msg)-1)!=-1) // just call socket recv
        {
            ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server recv : %s\n"),msg));
            //get current time
            ACE_Date_Time date;
            sprintf(msg,"%ld-%ld-%ld %02ld:%02ld:%02ld:%02ld",date.year(),date.month(),date.day(),date.hour(),date.minute(),date.second(),date.microsec());
            //发送数据
            stream.send_n(msg,sizeof(msg));
            ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("发送当前时间%s至 %s %d\n"),msg,raddr.get_host_addr(),raddr.get_port_number()));
            ACE_OS::sleep(1);
        }
    }
    else
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server建立链接失败\n")));
    }
    //关闭链接
    stream.close();
    ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server链接关闭了\n")));
    server.close();

    return 0;
}

Client端time_client_main.cpp

#include "ace/OS.h"
#include <ace/OS_main.h>
#include <ace/ACE.h>
#include <ace/Log_Msg.h>
#include <ace/SOCK_Connector.h>

int main(int argc, char *argv[])
{
    ACE_INET_Addr addr(1500,"127.0.0.1"); //remote address
    ACE_SOCK_Connector con; // connetor for socket client
    ACE_SOCK_Stream stream; // stream is for socket read/write

    //建立链接
    if(con.connect(stream,addr)==-1) //connect to remote address
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client建立链接失败\n")));
        return 1;
    }
    else
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client建立链接成功\n")));
    }

    const char msg[] = "I‘m Client ABC";
    //发送数据
    int n=3;
    for (int i=0; stream.send_n(msg,sizeof(msg)) != -1 && i<3;++i)
    {
        ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client send successed\n")));

        char buffer[1024] = {0};
        //接收数据
        if(stream.recv(buffer,sizeof(buffer)-1)==-1) // just call socket recv
        {
            ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client recv failed\n")));
            return 1;
        }
        else
        {
            ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client recv:%s\n"),buffer));
        }
        ACE_OS::sleep(1);
    }

    //断开链接
    if (stream.close () == -1) //close the connection
    {
        ACE_ERROR ((LM_ERROR,ACE_TEXT ("Client close failed\n")));
        return 1;
    }
    else
    {
        ACE_ERROR ((LM_ERROR,ACE_TEXT ("Client close successed\n")));
    }
    return 0;
}

TimerServer Edition 2.0  多次发送

多个client分多次发送

时间: 2024-08-25 00:33:16

一篇文章贯穿ACE各种发送接收组件 1.2版的相关文章

一篇文章贯穿ACE各种发送接收组件

通信过程 首先介绍一下socket通信的基本过程:这里先假设有两个家伙在通信,一个是S,另一个叫C (1)S打开端口监听本地的端口看看有没有人来连接: (2)与此同时C试图去连接远程的S,连接的地址就是S的地址加上S监听的端口号: (3)S收到C的请求之后,建立连接,双方共同持有连接的通道,可互相发送/接收数据任意次,此时S和C无区别: (4)其中一方断开连接,或者因为网络原因中断连接,另一方也会关闭: (5)此时通信过程结束: 整个过程如下图所示 普通的ACE通信类完成上面的通信过程: Tim

从缓冲上看阻塞与非阻塞socket在发送接收上的区别

最近在网络上看到一些帖子以及回复,同时又搜索了一些网络上关于阻塞非阻塞区别的描述,发现很多人在描述两者的发送接收时操作返回以及缓冲区处理的区别时有不同程度的误解.所以我想写一篇文章来纠正错误,并作为记录方便查阅,如有转载,注明作者(jwybobo2007)以及出处即可. 首先socket在默认情况下是阻塞状态的(未指异步操作以及其它一些特殊用途下,直接默认为非阻塞),这就使得发送以及接收操作处于阻塞的状态,即调用不会立即返回,而是进入睡眠等待操作完成.下面把讨论点分为发送以及接收.  一.发送选

一篇文章学会页面传值的10种方法(下)

一篇文章学会页面传值的10种方法(下) 6.代理委托实现页面之间的反向传值 这一种方法就是运用协议实现传值,这种方式也是在工程中常用的一种传值方法.首先创建好ViewController和SubViewController,在ViewController中创建好一个展示信息的Label,在SubViewController中创建好一个TextFeild,我们实现在第二个界面点击屏幕时,将TextFeild中的文字传到第一个界面,然后让背景颜色变色. 效果如下: 代理传值.gif 第一步: 首先我

一篇文章带你了解spring框架

虽然现在流行用SpringBoot了,很多配置已经简化和封装了,但是对于Spring的一些基础我们了解一些是对我们自己的架构思想很有帮助的!接下来和笔者一起来探讨一下Spring框架吧! 1.什么是Spring框架?Spring框架有哪些主要模块? Spring框架是一个为Java应用程序的开发提供了综合.广泛的基础性支持的Java平台.Spring帮助开发者解决了开发中基础性的问题,使得开发人员可以专注于应用程序的开发.Spring框架本身亦是按照设计模式精心打造,这使得我们可以在开发环境中安

一篇文章学会docker

一篇文章学会docker docker安装 docker在线安装 1.更新yum到最新 yum update 2.卸载旧版本 sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine 3.安装需要的软件

一篇文章看懂spark 1.3+各版本特性

Spark 1.6.x的新特性Spark-1.6是Spark-2.0之前的最后一个版本.主要是三个大方面的改进:性能提升,新的 Dataset API 和数据科学功能的扩展.这是社区开发非常重要的一个里程碑.1. 性能提升根据 Apache Spark 官方 2015 年 Spark Survey,有 91% 的用户想要提升 Spark 的性能.Parquet 性能自动化内存管理流状态管理速度提升 10X 2. Dataset APISpark 团队引入了 DataFrames,新型Datase

一篇文章学会页面传值的10种方法(上)

一篇文章学会页面传值的10种方法(上) 1.最简单AB面正向传值 效果如下: 最简单的正向传值.gif 首先我们先创建两个视图控制器ViewController.swift和SubViewController.swift 设置第一个界面 首先在第一个界面创建好一个TextFeild,用来写我们要传的文字 import UIKit class ViewController: UIViewController {     let textField = UITextField()     overr

一篇文章看懂Android学习最佳路线

为什么中高级Android程序员不多呢?这是一个问题,我不好回答,但是我想写一篇文章来描述下Android的学习路线,期望可以帮助更多的Android程序员提升自己. 作者:来源:Android开发中文站|2015-11-12 10:40 收藏 分享 前言 看到一篇文章中提到"最近几年国内的初级Android程序员已经很多了,但是中高级的Android技术人才仍然稀缺",这的确不假,从我在百度所进行的一些面试来看,找一个适合的高级Android工程师的确不容易,一般需要进行大量的面试才

Android:学习AIDL,这一篇文章就够了(上)

前言 在决定用这个标题之前甚是忐忑,主要是担心自己对AIDL的理解不够深入,到时候大家看了之后说--你这是什么玩意儿,就这么点东西就敢说够了?简直是坐井观天不知所谓--那样就很尴尬了.不过又转念一想,我辈年轻人自当有一种一往无前的锐气,标题大气一点岂不更好?并且大家都是文明人,总归更多的是理解与补充而不是侮辱与谩骂?所以最终还是厚颜用了这么一个不怎么有耻的标题. 好了,接下来进入正题,谈谈我对AIDL的理解和认识. 正文 1,概述 AIDL是一个缩写,全称是Android Interface D