I would like to send a string: "Jane Doe" to intranet ip 192.168.0.4 to port 9000 over UDP. I have done this many times via UDP and TCP by Java, but now I have to do it with standard C++ libraries and I can't find any samples only topics where people just can't make it work.
I know that I have to encode "Jane Doe" as array of bytes then just open socket, pack it in datagram and send it.
C++ is not my first language and this is small part of code I can't figure out, I've chosen UDP because it is always much simpler than TCP.
A good source for network programming is Beej's Guide to Network Programming. Below is some sample Unix code.
If this is Windows programming:
"sock" should be of type SOCKET instead of int.
Use closesocket instead of close
#include <winsock2.h> instead of all those unix headers
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <memory.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <errno.h>
#include <stdlib.h>
#include <iostream>
int resolvehelper(const char* hostname, int family, const char* service, sockaddr_storage* pAddr)
{
int result;
addrinfo* result_list = NULL;
addrinfo hints = {};
hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM; // without this flag, getaddrinfo will return 3x the number of addresses (one for each socket type).
result = getaddrinfo(hostname, service, &hints, &result_list);
if (result == 0)
{
//ASSERT(result_list->ai_addrlen <= sizeof(sockaddr_in));
memcpy(pAddr, result_list->ai_addr, result_list->ai_addrlen);
freeaddrinfo(result_list);
}
return result;
}
int main()
{
int result = 0;
int sock = socket(AF_INET, SOCK_DGRAM, 0);
char szIP[100];
sockaddr_in addrListen = {}; // zero-int, sin_port is 0, which picks a random port for bind.
addrListen.sin_family = AF_INET;
result = bind(sock, (sockaddr*)&addrListen, sizeof(addrListen));
if (result == -1)
{
int lasterror = errno;
std::cout << "error: " << lasterror;
exit(1);
}
sockaddr_storage addrDest = {};
result = resolvehelper("192.168.0.4", AF_INET, "9000", &addrDest);
if (result != 0)
{
int lasterror = errno;
std::cout << "error: " << lasterror;
exit(1);
}
const char* msg = "Jane Doe";
size_t msg_length = strlen(msg);
result = sendto(sock, msg, msg_length, 0, (sockaddr*)&addrDest, sizeof(addrDest));
std::cout << result << " bytes sent" << std::endl;
return 0;
}
This is very easy to do if you are willing to use the boost library.
Here is the code snippit
#include "boost/asio.hpp"
using namespace boost::asio;
...
io_service io_service;
ip::udp::socket socket(io_service);
ip::udp::endpoint remote_endpoint;
socket.open(ip::udp::v4());
remote_endpoint = ip::udp::endpoint(ip::address::from_string("192.168.0.4"), 9000);
boost::system::error_code err;
socket.send_to(buffer("Jane Doe", 8), remote_endpoint, 0, err);
socket.close();
I rewrote selbie's code to make it more C++-like and I minimized it a bit.
#include <iostream>
#include <string>
#include <arpa/inet.h> // htons, inet_addr
#include <netinet/in.h> // sockaddr_in
#include <sys/types.h> // uint16_t
#include <sys/socket.h> // socket, sendto
#include <unistd.h> // close
int main(int argc, char const *argv[])
{
std::string hostname{"192.168.0.4"};
uint16_t port = 9000;
int sock = ::socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in destination;
destination.sin_family = AF_INET;
destination.sin_port = htons(port);
destination.sin_addr.s_addr = inet_addr(hostname.c_str());
std::string msg = "Jane Doe";
int n_bytes = ::sendto(sock, msg.c_str(), msg.length(), 0, reinterpret_cast<sockaddr*>(&destination), sizeof(destination));
std::cout << n_bytes << " bytes sent" << std::endl;
::close(sock);
return 0;
}
For Windows, I took Mikolasan's minimised version of selbie's code and modified according to https://beej.us/guide/bgnet/html/#windows to get a small standalone example.
To get this to compile, you'll need to link the Winsock library.
#include <iostream>
#include <string>
#include <winsock2.h>
int main()
{
// Initialise Winsock DLL
// See https://beej.us/guide/bgnet/html/#windows
WSADATA wsaData;
// MAKEWORD(1,1) for Winsock 1.1, MAKEWORD(2,0) for Winsock 2.0
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
fprintf(stderr, "WSAStartup failed.\n");
exit(1);
}
// Set up connection and send
std::string hostname{ "192.168.0.4" };
uint16_t port = 9000;
SOCKET sock = ::socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in destination;
destination.sin_family = AF_INET;
destination.sin_port = htons(port);
destination.sin_addr.s_addr = inet_addr(hostname.c_str());
std::string msg = "Jane Doe";
int n_bytes = ::sendto(sock, msg.c_str(), msg.length(), 0, reinterpret_cast<sockaddr*>(&destination), sizeof(destination));
std::cout << n_bytes << " bytes sent" << std::endl;
::closesocket(sock);
// Clean up sockets library
WSACleanup();
return 0;
}
Related
I'm trying to implement sctp client-server model using boost.asio framework.
Currently I have this for server:
#include <boost/asio.hpp>
#include <iostream>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
using namespace boost;
int main(int argc,char * argv[]){
if (argc < 2){
exit(0);
}
unsigned short MY_PORT_NUM = atoi(argv[1]);
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(MY_PORT_NUM);
try {
asio::io_context io_service;
boost::asio::generic::seq_packet_protocol::endpoint endpoint((struct sockaddr *)&servaddr, sizeof(servaddr),IPPROTO_SCTP);
boost::asio::basic_socket_acceptor<asio::generic::seq_packet_protocol> acceptor(io_service,endpoint);
boost::system::error_code ec;
asio::generic::seq_packet_protocol::socket socket(io_service);
acceptor.accept(socket,ec);
if (ec){
std::cout << ec.message() << "\n";
}
} catch ( boost::system::error_code& e){
std::cerr << e.message() << std::endl;
}
return 0;
}
I got an error message "Operation not supported".
I've also tried to make it this way:
try {
asio::io_context io_service;
boost::asio::generic::seq_packet_protocol p(AF_INET,IPPROTO_SCTP);
boost::asio::generic::seq_packet_protocol::endpoint endpoint((struct sockaddr *)&servaddr, sizeof(servaddr),IPPROTO_SCTP);
boost::asio::basic_socket_acceptor<asio::generic::seq_packet_protocol> acceptor(io_service);
acceptor.open(p);
acceptor.bind(endpoint);
acceptor.listen();
boost::system::error_code ec;
asio::generic::seq_packet_protocol::socket socket(io_service);
acceptor.accept(socket,ec);
if (ec){
std::cout << ec.message() << "\n";
}
} catch ( boost::system::error_code& e){
std::cerr << e.message() << std::endl;
}
And I've got exactly the same result.
You can compile this code with:
g++ sctp_server.cc -o sctp_server -lboost_thread -lboost_coroutine
I have C-version of sctp server, that's works fine:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
static void die(const char *s) {
perror(s);
exit(1);
}
static void server(unsigned short port){
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
struct sctp_initmsg initmsg;
initmsg.sinit_max_attempts = 4;
initmsg.sinit_num_ostreams = 5;
initmsg.sinit_num_ostreams = 5;
int listen_fd = socket(AF_INET, SOCK_STREAM,IPPROTO_SCTP);
if (listen_fd < 0)
die("socket()");
if ( bind(listen_fd, (struct sockaddr *)&servaddr,sizeof(servaddr)) < 0)
die("bind()");
if ( setsockopt(listen_fd,IPPROTO_SCTP,SCTP_INITMSG,&initmsg,sizeof(initmsg)) < 0)
die("setsockopt()");
if ( listen(listen_fd,initmsg.sinit_max_instreams) < 0)
die("listen()");
for (;;){
char buffer[1024];
fputs("Waiting for connection\n",stdout);
int connect_fd = accept(listen_fd, (struct sockaddr *)NULL, NULL);
if (connect_fd < 0)
die("accept()");
fputs("New client connected\n",stdout);
struct sctp_sndrcvinfo sndrcvinfo;
int flags;
size_t bytesRcvd = sctp_recvmsg(connect_fd,buffer,sizeof(buffer),NULL,0,&sndrcvinfo,&flags);
if (bytesRcvd > 0){
printf("Received data : %s\n", buffer);
}
close(connect_fd);
}
}
int main(int argc, char * argv[]){
if (argc < 2)
die("Usage ./c_sctp_server <Port>");
unsigned short port = atoi(argv[1]);
server(port);
return 0;
}
You can compile this with: gcc c_sctp_server.c -o c_sctp_server -lsctp
The question is what is wrong with my boost.asio version?
Firstly, error_code is never raised. You probbably meant to catch system_error:
} catch (boost::system::system_error const& e) {
std::cerr << e.code().message() << " from " << e.code().location() << std::endl;
}
Note that you can often learn about the source location of the error as shown. In your case (slightly redacted):
Operation not supported from boost/asio/detail/reactive_socket_service.hpp:505:5 in function 'error_code reactive_socket_service<Protocol>::accept(implementation_type&, Socket&, endpoint_type*, error_code&)'
As the message indicates, accept is not supported by seq_packet_protocol. I think you are going to have more leverage starting from generic::stream_protocol which does know about connections ("associations" for SCTP).
You might also consider going from an existing POSIX SCTP example and gradually replacing bits by Asio.
Disclaimer: I'm not versed with SCTP. A casual glance at RFC 9260 makes me think it's not trivial to adapt, as the behaviors are pretty different (e.g. changing associations or peer addresses), even assuming you will be using POSIX API directly instead of also wrapping SCTP-specific socket options.
Using Error Code
Live On Coliru
#include <boost/asio.hpp>
#include <arpa/inet.h>
#include <iostream>
#include <linux/sctp.h>
#include <netinet/in.h>
namespace asio = boost::asio;
using boost::system::error_code;
int main(int argc, char* argv[]) {
std::vector args(argv + 1, argv + argc);
// if (args.size() != 2) exit(0);
uint16_t MY_PORT_NUM = atoi(args.at(0));
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(MY_PORT_NUM);
//using protocol = asio::generic::seq_packet_protocol;
using protocol = asio::generic::stream_protocol;
protocol::endpoint ep{
reinterpret_cast<struct sockaddr*>(&servaddr),
sizeof(servaddr),
IPPROTO_SCTP,
};
asio::io_context ioc;
asio::basic_socket_acceptor<protocol> acceptor(ioc);
error_code ec;
if (!ec)
acceptor.open({AF_INET, IPPROTO_SCTP}, ec);
if (!ec)
acceptor.bind(ep, ec);
if (!ec)
acceptor.listen(protocol::socket::max_listen_connections, ec);
protocol::socket socket(ioc);
if (!ec)
acceptor.accept(socket, ec);
std::cout << ec.message() << " from " << ec.location() << "\n";
}
Using Exceptions
Live On Coliru
#include <boost/asio.hpp>
#include <arpa/inet.h>
#include <iostream>
#include <linux/sctp.h>
#include <netinet/in.h>
namespace asio = boost::asio;
int main(int argc, char* argv[]) try {
std::vector args(argv + 1, argv + argc);
// if (args.size() != 2) exit(0);
uint16_t MY_PORT_NUM = atoi(args.front());
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(MY_PORT_NUM);
// using protocol = asio::generic::seq_packet_protocol;
using protocol = asio::generic::stream_protocol;
protocol::endpoint ep{
reinterpret_cast<struct sockaddr*>(&servaddr),
sizeof(servaddr),
IPPROTO_SCTP,
};
asio::io_context ioc;
asio::basic_socket_acceptor<protocol> acceptor(ioc);
acceptor.open({AF_INET, IPPROTO_SCTP});
acceptor.bind(ep);
acceptor.listen(protocol::socket::max_listen_connections);
protocol::socket socket(ioc);
acceptor.accept(socket);
} catch (boost::system::system_error const& se) {
std::cout << se.code().message() << " from " << se.code().location() << "\n";
}
At first, here is my source code :
#include "server.h"
#include <netinet/in.h>
#include <unistd.h>
#include <thread>
#include <iostream>
#include <arpa/inet.h>
#include <sys/socket.h>
Server::Server(int port)
{
m_Port = port;
int server_socket = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port);
server_address.sin_addr.s_addr = INADDR_ANY;
bind(server_socket, (sockaddr *)&server_address, sizeof(server_address));
listen(server_socket, SOMAXCONN);
m_Socket = server_socket;
}
Server::~Server()
{
close(m_Socket);
}
void Server::Process_Connection(const std::string message) const
{
std::cout << message << "\n";
}
void Server::Start() const
{
constexpr size_t BUFFER_SIZE = 4096;
for (;;)
{
char buffer[BUFFER_SIZE] = "";
sockaddr_in their_add;
int connection = accept(this->m_Socket, (sockaddr *)&their_add, NULL);
read(connection, buffer, 1024);
std::cout << "Received: " << buffer << "\n";
// std::cout << "Number of bytes read: " << val_read << "\n";
std::thread temp(&Server::Process_Connection, this, buffer);
temp.join();
}
}
The problem is that in the line 57, the connection
int connection = accept(this->m_Socket, (sockaddr*)&their_add, NULL);
gets a value of -1, which is an invalid connection.
Do you have any suggestions? I'm quite new to the socket programming.
Thank you in advance for your help
Instead of this:
int connection = accept(this->m_Socket, (sockaddr*)&their_add, NULL);
This:
socklen_t size = sizeof(their_add);
int connection = accept(this->m_Socket, (sockaddr*)&their_add, &size);
I have recently been learning about networking in Unix, and have written these 2 simple programs that waits for a connection, receives a message, then sends the same message back to the sender:
Send.cpp
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <iostream>
#include <unistd.h>
int main(int argc, char const *argv[])
{
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, "2000", &hints, &res);
int sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (auto error = connect(sockfd, res->ai_addr, res->ai_addrlen) < 0){
std::cout << strerror(errno) << '\n';
exit(1);
}
char msg[] = "Hello, World";
send(sockfd, &msg, sizeof(msg), 0);
char input[sizeof(msg)];
recv(sockfd, &input, sizeof(input), 0);
std::cout << input << '\n';
close(sockfd);
return 0;
}
receive.cpp
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/poll.h>
#include <iostream>
#include <unistd.h>
int main(int argc, char const *argv[])
{
struct addrinfo hints, *res;
int sockfd, new_fd;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, "2000", &hints, &res);
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(sockfd, res->ai_addr, res->ai_addrlen);
listen(sockfd, 5);
struct sockaddr_storage their_addr1;
socklen_t addr_size;
addr_size = sizeof(their_addr1);
new_fd = accept(sockfd, (struct sockaddr *)&their_addr1, &addr_size);
if (new_fd < 0)
{
std::cout << "Error" << '\n';
std::cout << strerror(errno) << '\n';
exit(1);
}
std::cout << "Accepted" << '\n';
char msg[255];
auto n = recv(new_fd, &msg, 255, 0);
std::cout << msg << '\n';
send(new_fd, &msg, n, 0);
close(sockfd);
close(new_fd);
return 0;
}
If I run receive.cpp, then quickly (within about 5 or so seconds) run send.cpp, (running both from the command line) the programs work perfectly, but if I take any longer than that, then the send program just always gets a Connection Refused error and the receive program never terminates. It was my understanding that the accept() call would block the rest of the application and continue listening until a valid connection appears. Is this not how it works? Any help would be great thank you.
Credit to #n. 1.8e9-where's-my-share m.
The problem is that the binding was failing due to a "Address already in use" that was being caused because the TCP/IP protocol waits for a specific time to make sure all packets have arrived before allowing the same IP and Port combo to be used again.
Fix:
Wait for the kernel to give up the port.
Set the the socket options to allow for reuse of the same port using the
setsockopt()
int yes=1;
if (setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof yes) == -1) {
perror("setsockopt");
exit(1);
}
I'm trying to complete a simple echo server. The goal is to repeat back the message to the client. The server and client both compile.The server is binded to localhost and port 8080. The client has the address, the port, and the message. When the client goes through the program to the sendto section, it stop and waits there. My goal it to have it sent to the server, and the server to send it back.
Problem: The client is send the message and the server is receiving it correctly but the server is not able to return the message. Please help!
SERVER SIDE CODE:
#include <iostream>
#include <string.h>
#include <fstream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 8080
using namespace std;
int main() {
int serSockDes, len, readStatus;
struct sockaddr_in serAddr, cliAddr;
char buff[1024] = {0};
char msg[] = "Hello to you too!!!\n";
//creating a new server socket
if((serSockDes = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation error...\n");
exit(-1);
}
//binding the port to ip and port
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(PORT);
serAddr.sin_addr.s_addr = INADDR_ANY;
if((bind(serSockDes, (struct sockaddr*)&serAddr, sizeof(serAddr))) < 0) {
perror("binding error...\n");
exit(-1);
}
readStatus = recvfrom(serSockDes, buff, 1024, 0, (struct sockaddr*)&cliAddr, (socklen_t*)&len);
buff[readStatus] = '\0';
cout<<buff;
cout<<len;
sendto(serSockDes, msg, strlen(msg), 0, (struct sockaddr*)&cliAddr, len);
return 0;
}
CLIENT SIDE CODE:
#include <iostream>
#include <fstream>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 8080
using namespace std;
int main(int argc, char** argv) {
int cliSockDes, readStatus, len;
struct sockaddr_in serAddr;
char msg[] = "Hello!!!\n";
char buff[1024] = {0};
//create a socket
if((cliSockDes = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation error...\n");
exit(-1);
}
//server socket address
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(PORT);
serAddr.sin_addr.s_addr = INADDR_ANY;
sendto(cliSockDes, msg, strlen(msg), 0, (struct sockaddr*)&serAddr, sizeof(serAddr));
readStatus = recvfrom(cliSockDes, buff, 1024, 0, (struct sockaddr*)&serAddr, (socklen_t*)&len);
buff[readStatus] = '\0';
cout<<buff;
return 0;
}
The client is trying to send its message to INADDR_ANY, which is wrong. It needs to send to a specific IP address instead. The server can listen to all of its local IP addresses using INADDR_ANY, that is fine, but the IP address that the client sends to must be one that the server listens on (or, if the client and server are on different network segments, the client must send to an IP that reaches the server's router, which then must forward the message to an IP that the server is listening on).
Also, your calls to recvfrom() and sendto() on both ends are lacking adequate error handling. In particular, the addrlen parameter of recvfrom() specifies the max size of the sockaddr buffer upon input, and upon output returns the actual size of the peer address stored in the sockaddr. But you are not initializing the len variable that you pass in as the addrlen, so recvfrom() is likely to fail with an error that you do not handle.
Try something more like this instead:
Server:
#include <iostream>
#include <string.h>
#include <fstream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;
#define PORT 8080
int main() {
int serSockDes, readStatus;
struct sockaddr_in serAddr, cliAddr;
socklen_t cliAddrLen;
char buff[1024] = {0};
char msg[] = "Hello to you too!!!\n";
//creating a new server socket
if ((serSockDes = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation error...\n");
exit(-1);
}
//binding the port to ip and port
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(PORT);
serAddr.sin_addr.s_addr = INADDR_ANY;
if ((bind(serSockDes, (struct sockaddr*)&serAddr, sizeof(serAddr))) < 0) {
perror("binding error...\n");
close(serSockDes);
exit(-1);
}
cliAddrLen = sizeof(cliAddr);
readStatus = recvfrom(serSockDes, buff, 1024, 0, (struct sockaddr*)&cliAddr, &cliAddrLen);
if (readStatus < 0) {
perror("reading error...\n");
close(serSockDes);
exit(-1);
}
cout.write(buff, readStatus);
cout << endl;
if (sendto(serSockDes, msg, strlen(msg), 0, (struct sockaddr*)&cliAddr, cliAddrLen)) < 0) {
perror("sending error...\n");
close(serSockDes);
exit(-1);
}
close(serSockDes);
return 0;
}
Client:
#include <iostream>
#include <fstream>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;
#define PORT 8080
int main(int argc, char** argv) {
int cliSockDes, readStatus;
struct sockaddr_in serAddr;
socklen_t serAddrLen;
char msg[] = "Hello!!!\n";
char buff[1024] = {0};
//create a socket
if ((cliSockDes = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation error...\n");
exit(-1);
}
//server socket address
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(PORT);
serAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (sendto(cliSockDes, msg, strlen(msg), 0, (struct sockaddr*)&serAddr, sizeof(serAddr)) < 0) {
perror("sending error...\n");
close(cliSockDes);
exit(-1);
}
serAddrLen = sizeof(serAddr);
readStatus = recvfrom(cliSockDes, buff, 1024, 0, (struct sockaddr*)&serAddr, &serAddrLen);
if (readStatus < 0) {
perror("reading error...\n");
close(cliSockDes);
exit(-1);
}
cout.write(buff, readStatus);
cout << endl;
close(cliSockDes);
return 0;
}
I want to know how to make an HTTP request through a proxy using Socket.
I was looking through documentation on Internet, and many people said that to do it I must connect to the proxy server and send a packet with the following header:
send(Socket, "CONNECT http://icanhazip.com:80 HTTP/1.0\r\n\r\n", strlen("CONNECT http://icanhazip.com:80 HTTP/1.0\r\n\r\n"), 0);
That website returns the current public IP, but, unfortunately, every proxy server I tried returned errors instead of the webpage's HTML source.
This is my actual code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
try {
int Socket = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in SockAddr;
memset(&SockAddr, 0, sizeof(SockAddr));
SockAddr.sin_port = htons(80);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = inet_addr("198.169.246.30");
int iResult = connect(Socket, (struct sockaddr *)& SockAddr, sizeof(SockAddr));
if (iResult != 0) {
std::cout << "I can't connect :(.";
getchar();
return 1;
}
std::cout << "Connected.\n";
send(Socket, "CONNECT http://icanhazip.com:80 HTTP/1.1\r\n\r\n", strlen("CONNECT http://icanhazip.com:80 HTTP/1.1\r\n\r\n"), 0);
char buffer[10000];
int nDataLength;
while ((nDataLength = recv(Socket, buffer, 10000, 0)) > 0) {
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
std::cout << buffer[i];
i += 1;
}
}
iResult = close(Socket);
}
catch (...) {
}
return 0;
}
What can I do to fix it? Or, what other solution should I look into?
Old Chinese proverb say, "before writing code, better to read specification"
https://www.rfc-editor.org/rfc/rfc7230
by following links in the document:
A client sending a CONNECT request MUST send the authority form of
request-target (Section 5.3 of [RFC7230]); i.e., the request-target
consists of only the host name and port number of the tunnel
destination, separated by a colon. For example,
CONNECT server.example.com:80 HTTP/1.1
Host: server.example.com:80
source: https://www.rfc-editor.org/rfc/rfc7231#section-4.3.6