Socket programming with C++

I have been studying and working with C++ language for sometimes now, but my aim is to use C++ for Network (socket) programming. I have tried to get eBooks on socket programming in C++, unfortunately, I'm yet to find one. Most have been written for C, C# and Java, but not C++. Is there any such book on "Programming Sockets in C++"?

Please I need this urgently...

Thanks
Last edited on
You can use socket programming for C in your C++ programs. I don't know of any C++ specific books on the subject but the underlying libraries are written in C anyway, although you can probably find a number of C++ libraries that make using the C libraries much easier.

closed account (o1vk4iN6)
You could look into Boost's Asio api. I'm pretty sure socket api differ from operating to operating system, as far as I know there is no standard.

http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/examples.html
Last edited on
@Galik....Thanks for your suggestion.

But do you mean I should use a book with for Socket programming in C and apply it to C++ program? How easy is that?
crosslink wrote:
But do you mean I should use a book with for Socket programming in C and apply it to C++ program? How easy is that?

Yes, its very easy because C++ is also C (to a large degree).

For much of my socket programming I often use a piece of code I adapted from code I found in the book "The C++ Standard Library - A Tutorial and Reference". It basically wraps the C socket library calls with a std::stream derived class to make using sockets rather like using files:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#pragma once
#ifndef _GALIK_SOCKETSTREAM_H
#define _GALIK_SOCKETSTREAM_H

/*-----------------------------------------------------------------.
| Copyright (C) 2011 Galik grafterman@googlemail.com               |
'------------------------------------------------------------------'

This code is was created from code (C) Copyright Nicolai M. Josuttis 2001
with the following Copyright Notice:
*/

/* The following code declares classes to read from and write to
 * file descriptore or file handles.
 *
 * See
 *      http://www.josuttis.com/cppcode
 * for details and the latest version.
 *
 * - open:
 *      - integrating BUFSIZ on some systems?
 *      - optimized reading of multiple characters
 *      - stream for reading AND writing
 *      - i18n
 *
 * (C) Copyright Nicolai M. Josuttis 2001.
 * Permission to copy, use, modify, sell and distribute this software
 * is granted provided this copyright notice appears in all copies.
 * This software is provided "as is" without express or implied
 * warranty, and with no claim as to its suitability for any purpose.
 *
 * Version: Jul 28, 2002
 * History:
 *  Jul 28, 2002: bugfix memcpy() => memmove()
 *                fdinbuf::underflow(): cast for return statements
 *  Aug 05, 2001: first public version
 */

 /*

Permission to copy, use, modify, sell and distribute this software
is granted under the same conditions.

'----------------------------------------------------------------*/

#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <streambuf>
#include <istream>
#include <ostream>

namespace galik { namespace net {

template<typename Char>
class basic_socketbuf
: public std::basic_streambuf<Char>
{
public:
	typedef Char char_type;
	typedef std::basic_streambuf<char_type> buf_type;
	typedef std::basic_ostream<char_type> stream_type;
	typedef typename buf_type::int_type int_type;
	typedef typename std::basic_streambuf<Char>::traits_type traits_type;

protected:

	static const int char_size = sizeof(char_type);
	static const int SIZE = 128;
	char_type obuf[SIZE] ;
	char_type ibuf[SIZE] ;

	int sock;

public:
	basic_socketbuf(): sock(0)
	{
		buf_type::setp(obuf, obuf + (SIZE - 1));
		buf_type::setg(ibuf, ibuf, ibuf);
	}

	virtual ~basic_socketbuf() { sync(); }

	void set_socket(int sock) { this->sock = sock; }
	int get_socket() { return this->sock; }

protected:

	int output_buffer()
	{
		int num = buf_type::pptr() - buf_type::pbase();
		if(send(sock, reinterpret_cast<char*>(obuf), num * char_size, 0) != num)
			return traits_type::eof();
		buf_type::pbump(-num);
		return num;
	}

	virtual int_type overflow(int_type c)
	{
		if(c != traits_type::eof())
		{
			*buf_type::pptr() = c;
			buf_type::pbump(1);
		}

		if(output_buffer() == traits_type::eof())
			return traits_type::eof();
		return c;
	}

	virtual int sync()
	{
		if(output_buffer() == traits_type::eof())
			return traits_type::eof();
		return 0;
	}

	virtual int_type underflow()
	{
		if(buf_type::gptr() < buf_type::egptr())
			return *buf_type::gptr();

		int num;
		if((num = recv(sock, reinterpret_cast<char*>(ibuf), SIZE * char_size, 0)) <= 0)
			return traits_type::eof();

		buf_type::setg(ibuf, ibuf, ibuf + num);
		return *buf_type::gptr();
	}
};

typedef basic_socketbuf<char> socketbuf;
typedef basic_socketbuf<wchar_t> wsocketbuf;

template<typename Char>
class basic_socketstream
: public std::basic_iostream<Char>
{
public:
	typedef Char char_type;
	typedef std::basic_iostream<char_type> stream_type;
	typedef basic_socketbuf<char_type> buf_type;

protected:
	buf_type buf;

public:
	basic_socketstream(): stream_type(&buf) {}
	basic_socketstream(int s): stream_type(&buf) { buf.set_socket(s); }

	void close()
	{
		if(buf.get_socket() != 0) ::close(buf.get_socket());
		stream_type::clear();
	}

	bool open(const std::string& host, uint16_t port)
	{
		close();
		int sd = socket(AF_INET, SOCK_STREAM, 0);
		sockaddr_in sin;
		hostent *he = gethostbyname(host.c_str());

		std::copy(reinterpret_cast<char*>(he->h_addr)
			, reinterpret_cast<char*>(he->h_addr) + he->h_length
			, reinterpret_cast<char*>(&sin.sin_addr.s_addr));
		sin.sin_family = AF_INET;
		sin.sin_port = htons(port);

		if(connect(sd, reinterpret_cast<sockaddr*>(&sin), sizeof(sin)) < 0)
			stream_type::setstate(std::ios::failbit);
		else
			buf.set_socket(sd);
		return *this;
	}
};

typedef basic_socketstream<char> socketstream;
typedef basic_socketstream<wchar_t> wsocketstream;

}} // galik::net

#endif // _GALIK_SOCKETSTREAM_H 

It allows you to use a socket as a std::iostream.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using namespace galik;

std::string google(const std::string& word)
{
	net::socketstream ss;
	ss.open("google.com", 80);
	ss << "GET " << "/search?q=" << word << " HTTP/1.1\r\n"; // TODO: URLEncode word
	ss << "Host: www.google.com" << "\r\n";
	ss << "User-Agent: MyProg: " << VERSION << "\r\n";
	ss << "Accept: text/html" << "\r\n";
	ss << "\r\n" << std::flush;

	char c;
	std::ostringstream oss;
	while(ss.get(c)) oss.put(c);

	return oss.str();
}

It is not very flexible with regards to the types of socket used but it could easily be adapted.
Last edited on
closed account (S6k9GNh0)
I really suggest against using BSD sockets or Winsock2 or whatever directly. There are plenty of networking libraries that abstract sockets. SDL and SFML provide a layer, ASIO is one of the most extensive I've seen yet, and you can find many other variations if you search around.

I always suggest against using anything OS specific directly.
Yes, I'd agree with computerquip. Use the basic socket libraries. They're somewhat system dependent but once you get the principle it's not too hard to make it system independent.

Side note: Why reporting saurabhgupta0527? His site looks non comercial and provides some valid information. So promote it here doesn't seem to me as such a crime...?
The BSD socket library is the reference implementation. If you use them, everyone will know what your doing.

All other socket libraries add environment specific improvements. To be fair the BSDs have implementation specific improvements (like OpenBSD's randomised ids and FreeBSD's zero copy buffers).

An alternative socket lib is Lacewing, that LB mentioned recently. That uses OS specific optimisations.
The book "UNIX: Network Programming" by W. Richard Stevens (rest his soul if there is such a thing) is still, IMO, the definitive book on network and data communications programming.

While it is rather specific to UNIX based sockets and daemon processes, it can be adapted to Windows and other OSes.
Last edited on
Topic archived. No new replies allowed.