热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

muduo之Socket和SocketsOps

     Socket.cc和SocketsOps.cc用来调用一个套接字设置选项和底层的socketAPI,也包括一些类型转换,记录一下,以后可以直接拿来用。Socket.ccC

         Socket.cc和SocketsOps.cc用来调用一个套接字设置选项和底层的socket API,也包括一些类型转换,记录一下,以后可以直接拿来用。

Socket.cc

// Copyright 2010, Shuo Chen. All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#include "muduo/net/Socket.h"
#include "muduo/base/Logging.h"
#include "muduo/net/InetAddress.h"
#include "muduo/net/SocketsOps.h"
#include
#include
#include // snprintf
using namespace muduo;
using namespace muduo::net;
Socket::~Socket()
{
sockets::close(sockfd_);
}
bool Socket::getTcpInfo(struct tcp_info* tcpi) const
{
socklen_t len = sizeof(*tcpi);
memZero(tcpi, len);
return ::getsockopt(sockfd_, SOL_TCP, TCP_INFO, tcpi, &len) == 0;
}
bool Socket::getTcpInfoString(char* buf, int len) const
{
struct tcp_info tcpi;
bool ok = getTcpInfo(&tcpi);
if (ok)
{
snprintf(buf, len, "unrecovered=%u "
"rto=%u ato=%u snd_mss=%u rcv_mss=%u "
"lost=%u retrans=%u rtt=%u rttvar=%u "
"sshthresh=%u cwnd=%u total_retrans=%u",
tcpi.tcpi_retransmits, // Number of unrecovered [RTO] timeouts
tcpi.tcpi_rto, // Retransmit timeout in usec
tcpi.tcpi_ato, // Predicted tick of soft clock in usec
tcpi.tcpi_snd_mss,
tcpi.tcpi_rcv_mss,
tcpi.tcpi_lost, // Lost packets
tcpi.tcpi_retrans, // Retransmitted packets out
tcpi.tcpi_rtt, // Smoothed round trip time in usec
tcpi.tcpi_rttvar, // Medium deviation
tcpi.tcpi_snd_ssthresh,
tcpi.tcpi_snd_cwnd,
tcpi.tcpi_total_retrans); // Total retransmits for entire connection
}
return ok;
}
void Socket::bindAddress(const InetAddress& addr)
{
sockets::bindOrDie(sockfd_, addr.getSockAddr());
}
void Socket::listen()
{
sockets::listenOrDie(sockfd_);
}
int Socket::accept(InetAddress* peeraddr)
{
struct sockaddr_in6 addr;
memZero(&addr, sizeof addr);
int cOnnfd= sockets::accept(sockfd_, &addr);
if (connfd >= 0)
{
peeraddr->setSockAddrInet6(addr);
}
return connfd;
}
void Socket::shutdownWrite()
{
sockets::shutdownWrite(sockfd_);
}
void Socket::setTcpNoDelay(bool on)
{
int optval = on ? 1 : 0;
::setsockopt(sockfd_, IPPROTO_TCP, TCP_NODELAY,
&optval, static_cast(sizeof optval));
// FIXME CHECK
}
void Socket::setReuseAddr(bool on)
{
int optval = on ? 1 : 0;
::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR,
&optval, static_cast(sizeof optval));
// FIXME CHECK
}
void Socket::setReusePort(bool on)
{
#ifdef SO_REUSEPORT
int optval = on ? 1 : 0;
int ret = ::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEPORT,
&optval, static_cast(sizeof optval));
if (ret <0 && on)
{
LOG_SYSERR <<"SO_REUSEPORT failed.";
}
#else
if (on)
{
LOG_ERROR <<"SO_REUSEPORT is not supported.";
}
#endif
}
void Socket::setKeepAlive(bool on)
{
int optval = on ? 1 : 0;
::setsockopt(sockfd_, SOL_SOCKET, SO_KEEPALIVE,
&optval, static_cast(sizeof optval));
// FIXME CHECK
}

SocketsOps.cc

// Copyright 2010, Shuo Chen. All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#include "muduo/net/SocketsOps.h"
#include "muduo/base/Logging.h"
#include "muduo/base/Types.h"
#include "muduo/net/Endian.h"
#include
#include
#include // snprintf
#include
#include // readv
#include
using namespace muduo;
using namespace muduo::net;
namespace
{
typedef struct sockaddr SA;
#if VALGRIND || defined (NO_ACCEPT4)
void setNonBlockAndCloseOnExec(int sockfd)
{
// non-block
int flags = ::fcntl(sockfd, F_GETFL, 0);
flags |= O_NONBLOCK;
int ret = ::fcntl(sockfd, F_SETFL, flags);
// FIXME check
// close-on-exec
flags = ::fcntl(sockfd, F_GETFD, 0);
flags |= FD_CLOEXEC;
ret = ::fcntl(sockfd, F_SETFD, flags);
// FIXME check
(void)ret;
}
#endif
} // namespace
const struct sockaddr* sockets::sockaddr_cast(const struct sockaddr_in6* addr)
{
return static_cast(implicit_cast(addr));
}
struct sockaddr* sockets::sockaddr_cast(struct sockaddr_in6* addr)
{
return static_cast(implicit_cast(addr));
}
const struct sockaddr* sockets::sockaddr_cast(const struct sockaddr_in* addr)
{
return static_cast(implicit_cast(addr));
}
const struct sockaddr_in* sockets::sockaddr_in_cast(const struct sockaddr* addr)
{
return static_cast(implicit_cast(addr));
}
const struct sockaddr_in6* sockets::sockaddr_in6_cast(const struct sockaddr* addr)
{
return static_cast(implicit_cast(addr));
}
int sockets::createNonblockingOrDie(sa_family_t family)
{
#if VALGRIND
int sockfd = ::socket(family, SOCK_STREAM, IPPROTO_TCP);
if (sockfd <0)
{
LOG_SYSFATAL <<"sockets::createNonblockingOrDie";
}
setNonBlockAndCloseOnExec(sockfd);
#else
int sockfd = ::socket(family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);
if (sockfd <0)
{
LOG_SYSFATAL <<"sockets::createNonblockingOrDie";
}
#endif
return sockfd;
}
void sockets::bindOrDie(int sockfd, const struct sockaddr* addr)
{
int ret = ::bind(sockfd, addr, static_cast(sizeof(struct sockaddr_in6)));
if (ret <0)
{
LOG_SYSFATAL <<"sockets::bindOrDie";
}
}
void sockets::listenOrDie(int sockfd)
{
int ret = ::listen(sockfd, SOMAXCONN);
if (ret <0)
{
LOG_SYSFATAL <<"sockets::listenOrDie";
}
}
int sockets::accept(int sockfd, struct sockaddr_in6* addr)
{
socklen_t addrlen = static_cast(sizeof *addr);
#if VALGRIND || defined (NO_ACCEPT4)
int cOnnfd= ::accept(sockfd, sockaddr_cast(addr), &addrlen);
setNonBlockAndCloseOnExec(connfd);
#else
int cOnnfd= ::accept4(sockfd, sockaddr_cast(addr),
&addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
#endif
if (connfd <0)
{
int savedErrno = errno;
LOG_SYSERR <<"Socket::accept";
switch (savedErrno)
{
case EAGAIN:
case ECONNABORTED:
case EINTR:
case EPROTO: // ???
case EPERM:
case EMFILE: // per-process lmit of open file desctiptor ???
// expected errors
errno = savedErrno;
break;
case EBADF:
case EFAULT:
case EINVAL:
case ENFILE:
case ENOBUFS:
case ENOMEM:
case ENOTSOCK:
case EOPNOTSUPP:
// unexpected errors
LOG_FATAL <<"unexpected error of ::accept " < break;
default:
LOG_FATAL <<"unknown error of ::accept " < break;
}
}
return connfd;
}
int sockets::connect(int sockfd, const struct sockaddr* addr)
{
return ::connect(sockfd, addr, static_cast(sizeof(struct sockaddr_in6)));
}
ssize_t sockets::read(int sockfd, void *buf, size_t count)
{
return ::read(sockfd, buf, count);
}
ssize_t sockets::readv(int sockfd, const struct iovec *iov, int iovcnt)
{
return ::readv(sockfd, iov, iovcnt);
}
ssize_t sockets::write(int sockfd, const void *buf, size_t count)
{
return ::write(sockfd, buf, count);
}
void sockets::close(int sockfd)
{
if (::close(sockfd) <0)
{
LOG_SYSERR <<"sockets::close";
}
}
void sockets::shutdownWrite(int sockfd)
{
if (::shutdown(sockfd, SHUT_WR) <0)
{
LOG_SYSERR <<"sockets::shutdownWrite";
}
}
void sockets::toIpPort(char* buf, size_t size,
const struct sockaddr* addr)
{
toIp(buf,size, addr);
size_t end = ::strlen(buf);
const struct sockaddr_in* addr4 = sockaddr_in_cast(addr);
uint16_t port = sockets::networkToHost16(addr4->sin_port);
assert(size > end);
snprintf(buf+end, size-end, ":%u", port);
}
void sockets::toIp(char* buf, size_t size,
const struct sockaddr* addr)
{
if (addr->sa_family == AF_INET)
{
assert(size >= INET_ADDRSTRLEN);
const struct sockaddr_in* addr4 = sockaddr_in_cast(addr);
::inet_ntop(AF_INET, &addr4->sin_addr, buf, static_cast(size));
}
else if (addr->sa_family == AF_INET6)
{
assert(size >= INET6_ADDRSTRLEN);
const struct sockaddr_in6* addr6 = sockaddr_in6_cast(addr);
::inet_ntop(AF_INET6, &addr6->sin6_addr, buf, static_cast(size));
}
}
void sockets::fromIpPort(const char* ip, uint16_t port,
struct sockaddr_in* addr)
{
addr->sin_family = AF_INET;
addr->sin_port = hostToNetwork16(port);
if (::inet_pton(AF_INET, ip, &addr->sin_addr) <= 0)
{
LOG_SYSERR <<"sockets::fromIpPort";
}
}
void sockets::fromIpPort(const char* ip, uint16_t port,
struct sockaddr_in6* addr)
{
addr->sin6_family = AF_INET6;
addr->sin6_port = hostToNetwork16(port);
if (::inet_pton(AF_INET6, ip, &addr->sin6_addr) <= 0)
{
LOG_SYSERR <<"sockets::fromIpPort";
}
}
int sockets::getSocketError(int sockfd)
{
int optval;
socklen_t optlen = static_cast(sizeof optval);
if (::getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) <0)
{
return errno;
}
else
{
return optval;
}
}
struct sockaddr_in6 sockets::getLocalAddr(int sockfd)
{
struct sockaddr_in6 localaddr;
memZero(&localaddr, sizeof localaddr);
socklen_t addrlen = static_cast(sizeof localaddr);//static_cast强制类型转换
if (::getsockname(sockfd, sockaddr_cast(&localaddr), &addrlen) <0)
{
LOG_SYSERR <<"sockets::getLocalAddr";
}
return localaddr;
}
struct sockaddr_in6 sockets::getPeerAddr(int sockfd)
{
struct sockaddr_in6 peeraddr;
memZero(&peeraddr, sizeof peeraddr);
socklen_t addrlen = static_cast(sizeof peeraddr);
if (::getpeername(sockfd, sockaddr_cast(&peeraddr), &addrlen) <0)
{
LOG_SYSERR <<"sockets::getPeerAddr";
}
return peeraddr;
}
bool sockets::isSelfConnect(int sockfd)
{
struct sockaddr_in6 localaddr = getLocalAddr(sockfd);
struct sockaddr_in6 peeraddr = getPeerAddr(sockfd);
if (localaddr.sin6_family == AF_INET)
{
const struct sockaddr_in* laddr4 = reinterpret_cast(&localaddr);
const struct sockaddr_in* raddr4 = reinterpret_cast(&peeraddr);
return laddr4->sin_port == raddr4->sin_port
&& laddr4->sin_addr.s_addr == raddr4->sin_addr.s_addr;
}
else if (localaddr.sin6_family == AF_INET6)
{
return localaddr.sin6_port == peeraddr.sin6_port
&& memcmp(&localaddr.sin6_addr, &peeraddr.sin6_addr, sizeof localaddr.sin6_addr) == 0;
}
else
{
return false;
}
}

 



推荐阅读
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 如何在文本中运行Java程序
    本文介绍了在文本中运行Java程序的步骤,包括创建文本文档、修改后缀、打开DOS命令窗口、编译和运行程序。通过这些步骤,可以在文本中成功运行Java程序并输出结果。 ... [详细]
author-avatar
g我爱他偶买噶
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有