基本的TCP/IP Socket用法(二)
来源:互联网 发布:淘宝交易网 编辑:程序博客网 时间:2024/06/05 11:28
1、前言
服务器端的构建,相比较构建客户更加困难。但若只考虑网络部分时,两种工作事实上是对等的。创建服务器时遇到的主要困难主要来自像并发和资源处理这样的问题。
(1)定义地址
(2)在该地址上打开用于侦听新连接的接受器,然后等待连接请求的到达
在等待过程中,要进行各种异常的处理,如错误编号是EINTR,表示网络出现问题,可继续等待;ETIMEDOUT表示超时,也可以继续等待。无论如何,若有有异常,最好写入一条日志记录,跟踪事件。
(3)若打开成功,将返回一个已经初始化的有效端对端对象,它代表与客户的连接。此后的通信中,服务器和客户端的区分已经不明显了,因为那是一个双向的对等通信。
2、服务器端代码(与前面客户端代码一起,可以配合运行)
以下是服务器端的代码:
// BaseSocket_Practice_Server.cpp : 定义控制台应用程序的入口点。
//
#define ACE_NTRACE 0
#include "ace/INET_Addr.h"
#include "ace/SOCK_Stream.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/Log_Msg.h"
#include "ace/Time_Value.h"
#include "ace/streams.h"//消息流文件重定向
#include "ace/Log_Record.h"//ACE_Log_Record对象定义
#include "ace/SString.h"
#include "define.h"
int ACE_TMAIN(int argc, ACE_TCHAR* argv[])
{
//ACE_OSTREAM_TYPE *output=new std::ofstream("server.test");
//ACE_LOG_MSG->msg_ostream(output);
//ACE_LOG_MSG->set_flags(ACE_Log_Msg::OSTREAM);//日志重定向到文件
//ACE_LOG_MSG->clr_flags(ACE_Log_Msg::STDERR);//禁用标准设备输出
ACE_TRACE(ACE_TEXT("server main"));
//服务器地址和端口
ACE_INET_Addr port_to_listen(5000,ACE_LOCALHOST);
//侦听器
ACE_SOCK_Acceptor acceptor;
//打开侦听器,设置端口可复用
if(acceptor.open(port_to_listen,1)==-1)
{
ACE_ERROR_RETURN((LM_ERROR,
ACE_TEXT("%p/n"),
ACE_TEXT("acceptor.open")),
100);
}
//可以接受多个客户端连接,但每次只能处理一个
while(1)
{
ACE_SOCK_Stream peer;
ACE_INET_Addr peer_addr;
ACE_Time_Value timeout(10,0);//用秒和微秒构造的时间:10秒,0微秒
//阻塞方式接受客户端连接
//由于最后一个参数设置为0,因此当返回错误是EINTR的时候,即连接中断时,循环退出
//但超时情形则不退出循环
if(acceptor.accept(peer,&peer_addr,&timeout,0)==-1)
{
if(ACE_OS::last_error()==EINTR)//连接中断
{
ACE_DEBUG((LM_DEBUG,
ACE_TEXT("(%p|%t) Interrupted while/n"),
ACE_TEXT("waitng for connection/n")));
}
else if(ACE_OS::last_error()==ETIMEDOUT)//等待超时,若超时写一条日志记录,但监听循环不退出
{
ACE_DEBUG((LM_DEBUG,
ACE_TEXT("(%p|%t) TimeOut while/n"),
ACE_TEXT("waiting for connection/n")));
}
}
else
{
ACE_TCHAR peer_name[MAXHOSTNAMELEN];
//获取客户端的IP地址和端口
peer_addr.addr_to_string(peer_name,MAXHOSTNAMELEN);
ACE_DEBUG((LM_DEBUG,ACE_TEXT("%s/n"),peer_name));
iovec buffer;
ssize_t bytes_received;
//将接收到的数据原封不动地给对端发送过去
while((bytes_received=peer.recvv(&buffer))!=-1)
{
if(bytes_received==0)
break;
ACE_DEBUG((LM_DEBUG,ACE_TEXT("%s%d/n"),ACE_reinterpret_cast(char*,buffer.iov_base),bytes_received));
peer.send_n(ACE_reinterpret_cast(char*,buffer.iov_base),bytes_received);
}
//每个客户端通信完毕,关闭流
peer.close();
ACE_DEBUG((LM_DEBUG,ACE_TEXT("Peer closed./n")));
}
}
//ACE_LOG_MSG->clr_flags(ACE_Log_Msg::OSTREAM);//非常重要,否则最后一条日志将尝试在已经删除的output对象上写
//delete output;//释放内存
return (0);
}
3、小结
(1)若只考虑网络的话,服务器端的创建与客户端的创建工作对等;
(2)本程序和前面文章中的客户端程序同时运行,演示客户端和服务器端的通信,服务器端将客户端发来的信息原封不动地回发给客户端。服务器端可以处理多个客户的连接,但每次只能服务一个客户;
(3)从日志信息定向来看,两个程序若在同一个计算机中运行的话,显然不能都写往同一个目标流。本例中,服务器端写往控制台,客户端则重定向到文件流;
(4)没有解决的问题是,重定向到文件流的日志,有乱码出现(控制台显示则没有,调试跟踪发现各变量也没有乱码字符)。这个问题没有解决。
- 基本的TCP/IP Socket用法(二)
- 基本的TCP/IP Socket用法(二)
- ACE 基本的 TCP/IP Socket 用法
- 基本的TCP/IP Socket用法(一)
- 基本的TCP/IP Socket用法(一)
- ACE学习笔记一(基本的TCP/IP Socket用法)
- Java Socket 几个重要的TCP/IP选项解析(二)
- Java Socket 几个重要的TCP/IP选项解析(二)
- socket中tcp 和 udp的基本用法
- TCP/IP socket programming in C(二)
- tcp ip http socket https 基本理解
- RIL & TCP/IP &Wireshark基本用法 好的学习博客
- Linux下TCP/IP socket 编程二
- SOCKET的TCP/IP编程
- TCP/IP的Socket编程
- Tcp/IP的理解-socket
- TCP/IP的Socket编程
- socket,TCP/IP的理解
- ACE篇之十一:ACE容器之六(自调整的二叉树)
- 基本的TCP/IP Socket用法(一)
- Device/PhysicalMemory Object
- 首选项添加
- SQL数据库维护计划
- 基本的TCP/IP Socket用法(二)
- ie8 开发人员工具 问题
- 处理事件及多个I/O流--ACE Reactor框架总览
- 今天开博,留个记号!
- SQL数据库维护计划2
- Editplus查找替换的正则表达式应用
- 非常好的awt放礼花程序 需要好好的看看 鼠标点击就 放的
- 不使用库函数,编写函数int strcmp(char *source, char *dest)
- 关于Linode的申请注册的文章