利用 ACE 来实现 UDP 通讯

TCP和UDP的"保护消息边界" 机制

        在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的。因此TCP的socket编程,收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。
       对于UDP,不会使用块的合并优化算法,这样,实际上目前认为,是由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。

保护消息边界和流

那么什么是保护消息边界和流呢?

       保护消息边界,就是指传输协议把数据当作一条独立的消息在网上 传输,接收端只能接收独立的消息.也就是说存在保护消息边界,接收 端一次只能接收发送端发出的一个数据包. 

       而面向流则是指无保护消息保护边界的,如果发送端连续发送数据, 接收端有可能在一次接收动作中,会接收两个或者更多的数据包.

       我们举个例子来说,例如,我们连续发送三个数据包,大小分别是2k, 4k , 8k,这三个数据包,都已经到达了接收端的网络堆栈中,如果使用UDP协议,不管我们使用多大的接收缓冲区去接收数据,我们必须有 三次接收动作,才能够把所有的数据包接收完.而使用TCP协议,我们只要把接收的缓冲区大小设置在14k以上,我们就能够一次把所有的 数据包接收下来.只需要有一次接收动作.这就是因为UDP协议的保护消息边界使得每一个消息都是独立的.而 流传输,却把数据当作一串数据流,他不认为数据是一个一个的消息.

 

      所以有很多人在使用tcp协议通讯的时候,并不清楚tcp是基于流的 传输,当连续发送数据的时候,他们时常会认识tcp会丢包.其实不然, 因为当他们使用的缓冲区足够大时,他们有可能会一次接收到两个甚 至更多的数据包,而很多人往往会忽视这一点,只解析检查了第一个数据包,而已经接收的其他数据包却被忽略了.所以大家如果要作这 类的网络编程的时候,必须要注意这一点.

 

结论:
     根据以上所说,可以这样理解,TCP为了保证可靠传输,尽量减少额外开销(每次发包都要验证),因此采用了流式传输,面向流的传输,相对于面向消息的传输,可以减少发送包的数量。从而减少了额外开销。但是,对于数据传输频繁的程序来讲,使用TCP可能会容易粘包。当然,对接收端的程序来讲,如果机器负荷很重,也会在接收缓冲里粘包。这样,就需要接收端额外拆包,增加了工作量。因此,这个特别适合的是数据要求可靠传输,但是不需要太频繁传输的场合(两次操作间隔100ms,具体是由TCP等待发送间隔决定的,取决于内核中的socket的写法)

     而UDP,由于面向的是消息传输,它把所有接收到的消息都挂接到缓冲区的接受队列中,因此,它对于数据的提取分离就更加方便,但是,它没有粘包机制,因此,当发送数据量较小的时候,就会发生数据包有效载荷较小的情况,也会增加多次发送的系统发送开销(系统调用,写硬件等)和接收开销。因此,应该最好设置一个比较合适的数据包的包长,来进行UDP数据的发送。(UDP最大载荷为1472,因此最好能
每次传输接近这个数的数据量,这特别适合于视频,音频等大块数据的发送,同时,通过减少握手来保证流媒体的实时性)

 

#pragma once

#include "ace/OS_main.h"
#include "ace/OS_NS_string.h"
#include "ace/OS_NS_unistd.h"
#include "ace/Reactor.h"
#include "ace/SOCK_Dgram.h"
#include "ace/INET_Addr.h"
#include "ace/Process.h"
#include "ace/Log_Msg.h"

class Dgram_Endpoint : public ACE_Event_Handler
{
public:
	Dgram_Endpoint(const ACE_INET_Addr &local_addr);
	~Dgram_Endpoint(void);
	virtual ACE_HANDLE get_handle(void) const;
	virtual int handle_input(ACE_HANDLE handle);
	virtual int handle_timeout(const ACE_Time_Value & tv, const void *arg = 0);
	virtual int handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask);
	int send(const char *buf, size_t len, const ACE_INET_Addr &);
private:
	ACE_SOCK_Dgram endpoint_;
};

#include "Dgram_Endpoint.h"


Dgram_Endpoint::Dgram_Endpoint(const ACE_INET_Addr &local_addr): endpoint_(local_addr)
{
}

Dgram_Endpoint::~Dgram_Endpoint(void)
{
}


int Dgram_Endpoint::send(const char *buf, size_t len, const ACE_INET_Addr &addr)
{
	return this->endpoint_.send (buf, len, addr);
}


ACE_HANDLE Dgram_Endpoint::get_handle (void) const
{
	return this->endpoint_.get_handle ();
}

int Dgram_Endpoint::handle_close (ACE_HANDLE handle, ACE_Reactor_Mask)
{
	ACE_UNUSED_ARG (handle);
	this->endpoint_.close ();
	delete this;
	return 0;
}

int Dgram_Endpoint::handle_input(ACE_HANDLE)
{
	char buf[BUFSIZ];
	memset(buf, 0, BUFSIZ);
	ACE_INET_Addr from_addr;

	ACE_DEBUG ((LM_DEBUG, "(%P|%t) activity occurred on handle %d!\n", this->endpoint_.get_handle ()));

	ssize_t n = this->endpoint_.recv (buf, sizeof buf, from_addr);

	if (n == -1)
	{
		ACE_ERROR ((LM_ERROR, "%p\n", "handle_input"));
	}
	else
	{
		ACE_DEBUG ((LM_DEBUG, "(%P|%t) buf of size %d = %*s\n", n, n, buf));
	}
	return 0;
}


int Dgram_Endpoint::handle_timeout (const ACE_Time_Value &, const void *)
{
	ACE_DEBUG ((LM_DEBUG, "(%P|%t) timed out for endpoint\n"));
	return 0;
}


 

#pragma once

#include "ace/Synch.h"
#include "ace/Task.h"
#include "Dgram_Endpoint.h"

class Customer_UI: public ACE_Task<ACE_MT_SYNCH>
{
public:
	Customer_UI(Dgram_Endpoint* dgram, ACE_INET_Addr remoaddr);
	~Customer_UI(void);
private:
	ACE_thread_t  threads[0x01];	
	Dgram_Endpoint* dgramep;
	ACE_INET_Addr remoteaddress;
public:
	virtual int open();
	virtual int svc();
};

#include "Customer_UI.h"


Customer_UI::Customer_UI(Dgram_Endpoint* dgram,  ACE_INET_Addr remoaddr)
{
	this->dgramep = dgram;
	this->remoteaddress = remoaddr;
}


Customer_UI::~Customer_UI(void)
{
}

int Customer_UI::open()
{
    return activate(THR_NEW_LWP, 1, 0, ACE_DEFAULT_THREAD_PRIORITY, -1, this, 0, 0, 0, threads);
}

int Customer_UI::svc()
{
	if (ACE_Thread::self() == threads[0])
	{	
		printf("threadid = %04d has been created\n", threads[0]);
		while(1)
		{
			printf("please input message:\n");
			char buff[BUFSIZ];
			memset(buff, 0, BUFSIZ);
			scanf("%s", buff);
			int length = strlen(buff);
			dgramep->send(buff, length, remoteaddress);
		}
	}
	return 0;
}


 

// NSVLR.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Dgram_Endpoint.h"
#include "Customer_UI.h"


int main(int argc, char* argv[])
{

	WSADATA wsaData;
	if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0) return 0;	

	u_short localport = 5050;
	const ACE_TCHAR *remotehost = "127.0.0.1";
	u_short remoteport = 6060;

	ACE_INET_Addr remote_addr(remoteport, remotehost);
	ACE_INET_Addr local_addr(localport);

	Dgram_Endpoint *endpoint;

	ACE_NEW_RETURN (endpoint, Dgram_Endpoint(local_addr), -1);

	if (ACE_Reactor::instance ()->register_handler(endpoint, ACE_Event_Handler::READ_MASK) == -1)
	{
		ACE_ERROR_RETURN ((LM_ERROR, "ACE_Reactor::register_handler"), -1);
	}

	Customer_UI *ui;
	ACE_NEW_RETURN (ui, Customer_UI(endpoint, remote_addr), -1);
	ui->open();

	while(true)
	{
		ACE_Reactor::instance()->handle_events();
	}

	return 0;
}


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C语言实现积分图实现ACE算法的代码: ```c #include <stdio.h> #include <stdlib.h> #include <opencv2/opencv.hpp> using namespace cv; void integral_image(Mat &img, Mat &integral) { int h = img.rows; int w = img.cols; integral.create(h+1, w+1, CV_32S); integral.setTo(0); for(int i=1; i<=h; i++) { for(int j=1; j<=w; j++) { integral.at<int>(i, j) = img.at<uchar>(i-1, j-1) + integral.at<int>(i-1, j) + integral.at<int>(i, j-1) - integral.at<int>(i-1, j-1); } } } void local_mean_and_variance(Mat &integral, int w_size, Mat &local_mean, Mat &local_variance) { int h = integral.rows - 1; int w = integral.cols - 1; int half_w_size = w_size / 2; local_mean.create(h, w, CV_32F); local_variance.create(h, w, CV_32F); for(int i=0; i<h; i++) { for(int j=0; j<w; j++) { int top = i - half_w_size; int left = j - half_w_size; int bottom = i + half_w_size; int right = j + half_w_size; top = top < 0 ? 0 : top; left = left < 0 ? 0 : left; bottom = bottom >= h ? h-1 : bottom; right = right >= w ? w-1 : right; int area = (bottom - top + 1) * (right - left + 1); int sum = integral.at<int>(bottom+1, right+1) + integral.at<int>(top, left) - integral.at<int>(bottom+1, left) - integral.at<int>(top, right+1); float mean = (float)sum / area; local_mean.at<float>(i, j) = mean; int sum2 = integral.at<int>(bottom+1, right+1) + integral.at<int>(top, left) - integral.at<int>(bottom+1, left) - integral.at<int>(top, right+1); float variance = (float)sum2 / area - mean * mean; local_variance.at<float>(i, j) = variance; } } } void contrast_score(Mat &local_mean, Mat &local_variance, float k, float alpha, Mat &contrast) { contrast.create(local_mean.rows, local_mean.cols, CV_32F); for(int i=0; i<local_mean.rows; i++) { for(int j=0; j<local_mean.cols; j++) { float mean = local_mean.at<float>(i, j); float variance = local_variance.at<float>(i, j); float score = k * fabs(mean) / sqrt(variance + alpha * alpha); contrast.at<float>(i, j) = score; } } } void contrast_enhancement(Mat &img, Mat &contrast, Mat &img_enhanced) { img.convertTo(img_enhanced, CV_32F); float *pImg = img_enhanced.ptr<float>(0); float *pContrast = contrast.ptr<float>(0); int size = img_enhanced.rows * img_enhanced.cols; for(int i=0; i<size; i++) { pImg[i] = pImg[i] + pContrast[i] * (pImg[i] - mean(pImg, size)); pImg[i] = pImg[i] < 0 ? 0 : pImg[i]; pImg[i] = pImg[i] > 255 ? 255 : pImg[i]; } img_enhanced.convertTo(img_enhanced, CV_8U); } int main(int argc, char **argv) { if(argc < 2) { printf("Usage: %s image_path\n", argv[0]); return -1; } Mat img = imread(argv[1], IMREAD_GRAYSCALE); if(img.empty()) { printf("Failed to load image: %s\n", argv[1]); return -1; } Mat integral, local_mean, local_variance, contrast, img_enhanced; integral_image(img, integral); local_mean_and_variance(integral, 21, local_mean, local_variance); contrast_score(local_mean, local_variance, 0.4, 1.0, contrast); contrast_enhancement(img, contrast, img_enhanced); imshow("original", img); imshow("enhanced", img_enhanced); waitKey(0); destroyAllWindows(); return 0; } ``` 其中,img_path 是待处理的图像路径,w_size 是局部均值和局部方差计算时的窗口大小,k 和 alpha 是对比度得分计算时的参数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值