All Projects → fpagliughi → Sockpp

fpagliughi / Sockpp

Licence: bsd-3-clause
Modern C++ socket library.

Programming Languages

cpp
1120 projects

Projects that are alternatives of or similar to Sockpp

Hp Socket
High Performance TCP/UDP/HTTP Communication Component
Stars: ✭ 4,420 (+1696.75%)
Mutual labels:  network, socket
Vibe Core
Repository for the next generation of vibe.d's core package.
Stars: ✭ 56 (-77.24%)
Mutual labels:  network, socket
Kalm
Moved to https://github.com/kalm/kalm.js
Stars: ✭ 449 (+82.52%)
Mutual labels:  network, socket
Network
Low-level networking interface
Stars: ✭ 255 (+3.66%)
Mutual labels:  network, socket
Ether.network
https://github.com/Eastrall/Sylver
Stars: ✭ 147 (-40.24%)
Mutual labels:  network, socket
Coderyi.github.io
Don't fork! coderyi's blog,about iOS ,CS and my code life.
Stars: ✭ 349 (+41.87%)
Mutual labels:  network, socket
Tinytcpserver
A small tcp server working under Mono or .NET (4.0) and provides hooks for handling data exchange with clients (works under mono and .net). Behaviour/protocol/reaction could be specified via custom C# script.
Stars: ✭ 14 (-94.31%)
Mutual labels:  network, socket
Hisocket
It is a lightweight client socket solution, you can used it in C# project or Unity3d
Stars: ✭ 275 (+11.79%)
Mutual labels:  network, socket
Pesocket
A C# Network Library.
Stars: ✭ 134 (-45.53%)
Mutual labels:  network, socket
Deta cache
缓存cache服务器
Stars: ✭ 106 (-56.91%)
Mutual labels:  network, socket
Clientserverproject
一个C-S模版,该模版由三部分的程序组成,一个服务端运行的程序,一个客户端运行的程序,还有一个公共的组件,实现了基础的账户管理功能,版本控制,软件升级,公告管理,消息群发,共享文件上传下载,批量文件传送功能。具体的操作方法见演示就行。本项目的一个目标是:提供一个基础的中小型系统的C-S框架,客户端有三种模式,无缝集成访问,winform版本,wpf版本,asp.net mvc版本,方便企业进行中小型系统的二次开发和个人学习。同时网络组件方便的支持读写三菱和西门子PLC的数据,详细见Readme
Stars: ✭ 873 (+254.88%)
Mutual labels:  network, socket
Zserver4d
ZServer4D 是一套从商业项目剥离而出的云服务器中间件,可以承载百万级的分布式负载服务,并且支持IoT及内网穿透
Stars: ✭ 199 (-19.11%)
Mutual labels:  network, socket
Fccss
Computer Science SCHOOL resources
Stars: ✭ 84 (-65.85%)
Mutual labels:  network, socket
Kalm.js
The socket manager
Stars: ✭ 155 (-36.99%)
Mutual labels:  network, socket
Pypacker
📦 The fastest and simplest packet manipulation lib for Python
Stars: ✭ 216 (-12.2%)
Mutual labels:  network, socket
Chameleon
Customizable honeypots for monitoring network traffic, bots activities and username\password credentials (DNS, HTTP Proxy, HTTP, HTTPS, SSH, POP3, IMAP, STMP, RDP, VNC, SMB, SOCKS5, Redis, TELNET, Postgres and MySQL)
Stars: ✭ 230 (-6.5%)
Mutual labels:  network
Chattt
❯❯❯ Chat without leaving your terminal
Stars: ✭ 239 (-2.85%)
Mutual labels:  socket
Sjnetwork
SJNetwork is a high level network request tool based on AFNetworking and inspired on YTKNetwork.
Stars: ✭ 231 (-6.1%)
Mutual labels:  network
Ssokit Qmake
A Simple & Strong Tool for TCP&UDP Debug
Stars: ✭ 231 (-6.1%)
Mutual labels:  socket
Unitysocketprotobuf3demo
主要实现了用Unity对接了Leaf服务器。其次带了些小工具。
Stars: ✭ 244 (-0.81%)
Mutual labels:  socket

sockpp

Build Status

Simple, modern, C++ socket library.

This is a fairly low-level C++ wrapper around the Berkeley sockets library using socket, acceptor, and connector classes that are familiar concepts from other languages.

The base socket class wraps a system socket handle, and maintains its lifetime. When the C++ object goes out of scope, it closes the underlying socket handle. Socket objects are generally moveable but not copyable. A socket can be transferred from one scope (or thread) to another using std::move().

Currently supports: IPv4, IPv6, and Unix-Domain Sockets on Linux, Mac, and Windows. Other *nix and POSIX systems should work with little or no modification.

All code in the library lives within the sockpp C++ namespace.

Latest News

The library is reaching a stable API, and is on track for a 1.0 release in the near future. Until then, there may be a few more breaking changes, but hopefully those will be fewer than we have seen so far.

On that note, despite being recently refactored and re-versioned at 0.x, earlier implementations of this library have been in use on production systems since ~2003, particularly with remote embedded Linux data loggers. Things that we now call IoT gateways and edge devices. It can be counted on to be reliable.

To keep up with the latest announcements for this project, follow me at:

Twitter: @fmpagliughi

If you're using this library, tweet at me or send me a message, and let me know how you're using it. I'm always curious to see where it's wound up!

Unreleased Features in this Branch

The following updates exist in this branch in the repository, but have yet to be formally released:

  • [#37] socket::get_option() not returning length on Windows.
  • [#39] Using SSIZE_T for ssize_t in Windows
  • Now acceptor::open() uses the SO_REUSEPORT option instead of SO_REUSEADDR on non-Windows systenms. Also made reuse optional.

New in v0.7

This release mainly targeted bug fixes, API inconsistencies, and numerous small features that had been overlooked previously.

  • Base socket class
    • shutdown() added
    • create() added
    • bind() moved into base socket (from acceptor)
  • Unix-domain socket pairs (stream and datagram)
  • Non-blocking I/O
  • Scatter/Gather I/O
  • stream_socket cloning.
  • Set and get socket options using template types.
  • stream_socket::read_n() and write_n() now properly handle EINTR return.
  • to_timeval() can convert from any std::chrono::duration type.
  • socket::close() and shutdown() check for errors, set last error, and return a bool.
  • tcpechomt.cpp: Example of a client sharing a socket between read and write threads - using clone().
  • Windows enhancements:
    • Implemented socket timeouts on Windows
    • Fixed bug in Windows socket cloning.
    • Fixed bug in Windows socket::last_error_string.
    • Unit tests working on Windows
  • More unit tests

Contributing

Contributions are accepted and appreciated. New and unstable work is done in the develop branch Please submit all pull requests against that branch, not master.

For more information, refer to: CONTRIBUTING.md

TODO

  • Unit Tests - The framework for unit and regression tests is in place (using Catch2), along with the GitHub Travis CI integration. But the library could use a lot more tests.
  • Consolidate Header Files - The last round of refactoring left a large number of header files with a single line of code in each. This may be OK, in that it separates all the protocols and families, but seems a waste of space.
  • Secure Sockets - It would be extremely handy to have support for SSL/TLS built right into the library as an optional feature.
  • SCTP - The SCTP protocol never caught on, but it seems intriguing, and might be nice to have in the library for experimentation, if not for some internal applications.

Building the Library

CMake is the supported build system.

Requirements:

  • A conforming C++-14 compiler.
    • gcc v5.0 or later (or) clang v3.8 or later.
    • Visual Studio 2015, or later on WIndows.
  • CMake v3.5 or newer.
  • Doxygen (optional) to generate API docs.
  • Catch2 (optional) to build and run unit tests.

Build like this on Linux:

$ cd sockpp
$ mkdir build ; cd build
$ cmake ..
$ make
$ sudo make install

Build Options

The library has several build options via CMake to choose between creating a static or shared (dynamic) library - or both. It also allows you to build the example options, and if Doxygen is

Variable Default Value Description
SOCKPP_BUILD_SHARED ON Whether to build the shared library
SOCKPP_BUILD_STATIC OFF Whether to build the static library
SOCKPP_BUILD_DOCUMENTATION OFF Create and install the HTML based API documentation (requires Doxygen)
SOCKPP_BUILD_EXAMPLES OFF Build example programs
SOCKPP_BUILD_TESTS OFF Build the unit tests (requires Catch2)

TCP Sockets

TCP and other "streaming" network applications are usually set up as either servers or clients. An acceptor is used to create a TCP/streaming server. It binds an address and listens on a known port to accept incoming connections. When a connection is accepted, a new, streaming socket is created. That new socket can be handled directly or moved to a thread (or thread pool) for processing.

Conversely, to create a TCP client, a connector object is created and connected to a server at a known address (typically host and socket). When connected, the socket is a streaming one which can be used to read and write, directly.

For IPv4 the tcp_acceptor and tcp_connector classes are used to create servers and clients, respectively. These use the inet_address class to specify endpoint addresses composed of a 32-bit host address and a 16-bit port number.

TCP Server: tcp_acceptor

The tcp_acceptor is used to set up a server and listen for incoming connections.

int16_t port = 12345;
sockpp::tcp_acceptor acc(port);

if (!acc)
    report_error(acc.last_error_str());

// Accept a new client connection
sockpp::tcp_socket sock = acc.accept();

The acceptor normally sits in a loop accepting new connections, and passes them off to another process, thread, or thread pool to interact with the client. In standard C++, this could look like:

while (true) {
    // Accept a new client connection
    sockpp::tcp_socket sock = acc.accept();

    if (!sock) {
        cerr << "Error accepting incoming connection: "
            << acc.last_error_str() << endl;
    }
    else {
        // Create a thread and transfer the new stream to it.
        thread thr(run_echo, std::move(sock));
        thr.detach();
    }
}

The hazards of a thread-per-connection design is well documented, but the same technique can be used to pass the socket into a thread pool, if one is available.

See the tcpechosvr.cpp example.

TCP Client: tcp_connector

The TCP client is somewhat simpler in that a tcp_connector object is created and connected, then can be used to read and write data directly.

sockpp::tcp_connector conn;
int16_t port = 12345;

if (!conn.connect(sockpp::inet_address("localhost", port)))
    report_error(conn.last_error_str());

conn.write_n("Hello", 5);

char buf[16];
ssize_t n = conn.read(buf, sizeof(buf));

See the tcpecho.cpp example.

UDP Socket: udp_socket

UDP sockets can be used for connectionless communications:

sockpp::udp_socket sock;
sockpp::inet_address addr("localhost", 12345);

std::string msg("Hello there!");
sock.send_to(msg, addr);

sockpp::inet_address srcAddr;

char buf[16];
ssize_t n = sock.recv(buf, sizeof(buf), &srcAddr);

See the udpecho.cpp and udpechosvr.cpp examples.

IPv6

The same style of connectors and acceptors can be used for TCP connections over IPv6 using the classes:

inet6_address
tcp6_connector
tcp6_acceptor
tcp6_socket
udp6_socket

Examples are in the examples/tcp directory.

Unix Domain Sockets

The same is true for local connection on *nix systems that implement Unix Domain Sockets. For that use the classes:

unix_address
unix_connector
unix_acceptor
unix_socket  (unix_stream_socket)
unix_dgram_socket

Examples are in the examples/unix directory.

Implementation Details

The socket class hierarchy is built upon a base socket class. Most simple applications will probably not use socket directly, but rather use top-level classes defined for a specific address family like tcp_connector and tcp_acceptor.

The socket objects keep a handle to an underlying OS socket handle and a cached value for the last error that occurred for that socket. The socket handle is typically an integer file descriptor, with values >=0 for open sockets, and -1 for an unopened or invalid socket. The value used for unopened sockets is defined as a constant, INVALID_SOCKET, although it usually doesn't need to be tested directly, as the object itself will evaluate to false if it's uninitialized or in an error state. A typical error check would be like this:

tcp_connector conn({"localhost", 12345});

if (!conn)
    cerr << conn.last_error_str() << std::endl;

The default constructors for each of the socket classes do nothing, and simply set the underlying handle to INVALID_SOCKET. They do not create a socket object. The call to actively connect a connector object or open an acceptor object will create an underlying OS socket and then perform the requested operation.

An application can generally perform most low-level operations with the library. Unconnected and unbound sockets can be created with the static create() function in most of the classes, and then manually bind and listen on those sockets.

The socket::handle() method exposes the underlying OS handle which can then be sent to any platform API call that is not exposed by the library.

Thread Safety

A socket object is not thread-safe. Applications that want to have multiple threads reading from a socket or writing to a socket should use some form of serialization, such as a std::mutex to protect access.

A socket can be moved from one thread to another safely. This is a common pattern for a server which uses one thread to accept incoming connections and then passes off the new socket to another thread or thread pool for handling. This can be done like:

sockpp::tcp6_socket sock = acc.accept(&peer);

// Create a thread and transfer the new socket to it.
std::thread thr(handle_connection, std::move(sock));

In this case, handle_connection would be a function that takes a socket by value, like:

void handle_connection(sockpp::tcp6_socket sock) { ... }

Since a socket can not be copied, the only choice would be to move the socket to a function like this.

It is a common patern, especially in client applications, to have one thread to read from a socket and another thread to write to the socket. In this case the underlying socket handle can be considered thread safe (one read thread and one write thread). But even in this scenario, a sockpp::socket object is still not thread-safe due especially to the cached error value. The write thread might see an error that happened on the read thread and visa versa.

The solution for this case is to use the socket::clone() method to make a copy of the socket. This will use the system's dup() function or similar create another socket with a duplicated copy of the socket handle. This has the added benefit that each copy of the socket can maintain an independent lifetime. The underlying socket will not be closed until both objects go out of scope.

sockpp::tcp_connector conn({host, port});

auto rdSock = conn.clone();
std::thread rdThr(read_thread_func, std::move(rdSock));

The socket::shutdown() method can be used to communicate the intent to close the socket from one of these objects to the other without needing another thread signaling mechanism.

See the tcpechomt.cpp example.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].