I got a captured tcp stream file that I need to simulate as if it was streaming the same bits again. I start by opening a linux console and run the following:
nc -l 12566 < capture.tcp
Now I want to write a ´c++´ code that can connect to this port 12566 and start processing those streams.
struct addrinfo hints, *res;
int m_sockfd
std::memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(null, '12566', &hints, &res);
m_socket = socket(res->ai_family,res->ai_socktype, res->ai_protocol);
bind(m_sockfd, res->ai_addr, res->ai_addrlen);
The binding function returns an error, and I think the reason is that it tries to bind to port that I only have opened with my linux console.
I am not sure how I can reach my objective by having a c++ that can receive the incoming tcp streams. Is what I am trying to do even possible, or do I actually also need to implement the server side ?
Related
I have a short program to send UDP data to a local socket like so.
const char *i = "localhost";
const char *p = "8980";
struct addrinfo h;
struct addrinfo *res = 0;
memset(&hints,0,sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = 0;
hints.ai_flags = AI_ADDRCONFIG;
if (getaddrinfo(i, p, &hints, &res) != 0)
{
printf("ERROR: getaddinfo\n");
}
int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (fd == -1)
{
printf("ERROR: socket\n");
freeaddrinfo(res);
}
if (sendto(fd, "hello", 5, 0, res->ai_addr, res->ai_addrlen) == -1)
{
printf("ERROR: Sending\n");
}
freeaddrinfo(res);
close(fd);
I have launched ncat in a different terminal window with ncat -ul localhost 8980 and I can see "hello" on it when I subsequently launch the above program. I can also perform repeated calls to sendto and see hello multiple times. The program terminates but I cannot see an additional "hello" message on ncat when I relaunch the sending program. Why is this?
I've also tried not calling close at the end of the program as well.
The issue is that every time you run your program it will send its data from a different port, and thus be seen as a different network endpoint. When ncat
first receives a packet, it will bind to the remote endpoint and stop listening for packets coming from any other endpoint.
You can work around this with ncat by using the -k option. Sadly, ncat's -k option can only be used with the -e or -c options when doing UDP. You can make it work with:
ncat -ulkc "cat > $(tty)" localhost 8980
It will still bind to each remote endpoint it gets anything from though, so there's a limit to the number of times it will work (default 100, configurable via the -m option).
It's a bit easier if you use nc instead. It's -k option works normally with -u:
nc -ulk localhost 8980
That will prevent nc from binding to the remote endpoint at all, so it doesn't have the same limit as ncat.
I am currently learning about the internet. I am trying to set up a simple proxy server that just forwards a request from the server side to its client side. Im currently following this tutorial. This is how far I have gotten:
#define MYPORT "3490" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
int main(int argc, const char* argv[]) {
struct addrinfo hints;
struct addrinfo *res;
int sockIn;
int sockOut;
memset(&hints, 0, sizeof hints); // make sure its empty
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM; // what kind of socket
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
//listens on the hosts ip address:
getaddrinfo(NULL, MYPORT, &hints, &res);
// make a socket, bind it, and listen on it:
sockIn = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(sockIn, res->ai_addr, res->ai_addrlen);
listen(sockIn, BACKLOG);
freeaddrinfo(res); // free the linked-list
struct sockaddr_storage their_addr;
socklen_t addr_size;
char buf[512];
while(1) {
addr_size = sizeof their_addr;
struct sockaddr *addr = (struct sockaddr *)&their_addr;
sockOut = accept(sockIn, addr, &addr_size);
recv(sockOut, buf, sizeof buf, 0);
for (auto ch : buf) {
cout << ch;
}
close(sockOut);
}
}
Right now im just displaying "hi" on every page I visit.
Before I implement the client side of the proxy id like to instead display the HTTP Get Request that my browser sends to the server side of the proxy. My issue is that I dont know how to retrieve it. The guide I'm using is not adressering this.
Edit: I added a recv call that is suppose to read everything from the socket in to a buffer. Unfortunately it does not cout anything
download and install wireshark (packet sniffer), or else Fiddler Fiddler(HTTP proxy). You will easily be able to inspect HTTP traffic. I recommend you start with fiddler. Install on computer where your browser is located.
I've just started using winsock, and it seems like it's only making a server on the local machine by default, rather than accepting external connections (from other computers on the system). I'm looking for the C++ equivalent of socket.bind(("192.168.0.112", 1024)) in Python (rather than "localhost")
If you want to bind to all adapters, which is the most common thing to do for accepting connections from both localhost and remote addresses, then this is all you really have to do:
sock = socket(AF_INET, SOCK_STREAM, 0); // SOCK_STREAM==TCP. Use SOCK_DGRAM if you want UDP
sockaddr_in addr = {}; // ={} is zero-init. Since INADDR_ANY is 0, it implicitly sets this as well
addr.sin_family = AF_INET;
addr.sin_port = htons(1024); // port 1024 in network byte order
int result = bind(sock, (sockaddr*)&addr, sizeof(addr));
I'm programming a server/client system using winsock2 and it works great when I connect the client to the server name or the server IPv6 address. However, when I use the server IPv4 address I get error "Connection refused" from the call to connect() in the client.
This error occurs with either my client or using telnet. However, I can successfully ping the server using either of the three name, IPv4 or IPv6.
I've tried this running both server and client on the same machine, on separate machines, and firewalls deactivated on all machines.
Here is an excerpt of my server initialization and listening code:
SOCKET sockfd = INVALID_SOCKET, in_socketID;
struct addrinfo hints;
struct addrinfo *servinfo = NULL;
struct addrinfo *p;
struct addrinfo *ip;
sockaddr_storage incoming_addr;
int addr_size;
int tmp_err;
const char *sPort = "20152";
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // either IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
tmp_err = getaddrinfo(NULL, sPort, &hints, &servinfo);
if (tmp_err != 0)
throw exception("ERROR: getaddrinfo failed");
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL && sockfd == INVALID_SOCKET; p = p->ai_next)
{
ip = p;
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockfd == INVALID_SOCKET)
{
cerr << "ERROR on socket(): " << WSAGetLastError() << endl;
} // end if
else if (bind(sockfd, p->ai_addr, p->ai_addrlen) == SOCKET_ERROR)
{
cerr << "ERROR on bind(): " << WSAGetLastError() << endl;
closesocket(sockfd);
sockfd = INVALID_SOCKET;
} // end if
} // end for
if (sockfd == INVALID_SOCKET)
{
// looped off the end of the list with no successful bind
throw exception("ERROR: Failed to bind socket");
}
// clean up
if (servinfo)
freeaddrinfo(servinfo);
if (listen(sockfd, SOMAXCONN ) == SOCKET_ERROR)
throw exception("Listen failed");
while (true)
{
memset(&incoming_addr, 0, sizeof(incoming_addr));
addr_size = sizeof(incoming_addr);
in_socketID = accept(socketID, (sockaddr *)&incoming_addr, &addr_size);
// do stuff with incoming connection
}
This is my client code:
int sockfd = INVALID_SOCKET;
struct addrinfo hints;
struct addrinfo *servinfo = NULL;
struct addrinfo *p;
struct addrinfo *ip;
int tmp_err;
const char *sHost = "192.168.1.136";
const char *sPort = "20152";
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // either IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // use TCP
tmp_err = getaddrinfo(sHost, // web address or ip to connect to
sPort, // port or protocol
&hints, // initialized hints structure
&servinfo); // return structure
if (tmp_err != 0)
throw exception("ERROR: getaddrinfo failed");
// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL && sockfd == INVALID_SOCKET; p = p->ai_next)
{
ip = p;
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockfd == INVALID_SOCKET)
{
cerr << "ERROR on socket(): " << WSAGetLastError() << endl;
//continue;
} // end if
else if (connect(sockfd, p->ai_addr, p->ai_addrlen) < 0)
{
cerr << "ERROR on connect(): " << WSAGetLastError() << endl;
closesocket(sockfd);
sockfd = INVALID_SOCKET;
//continue;
} // end if
} // end for
if (sockfd == INVALID_SOCKET)
throw exception("ERROR: Failed to connect");
// clean up
if (servinfo)
freeaddrinfo(servinfo);
// do stuff with new socket
I already read several similar questions in the site, but none answered this issue.
How can I connect also to the server IPv4 address? I need help, please.
Thanks.
EDIT:
From a suggestion given by user Sorayuki, I made some changes just to test if his theory was correct.
I was able to connect to the IPv4 by changing on the server
hints.ai_family = AF_UNSPEC;
to
hints.ai_family = AF_INET;
I knew it would obviously work, but when I do this, of course IPv6 doesn't work.
It appears user Sorayuki was right and my loop was connecting to IPv6.
It seems that there is no easy way to unify IPv6 and IPv4. Your socket must listen to either one or the other which makes the process really annoying.
According to the documentation, the old style to listen to both IPv4 and IPv6 is to create a socket for each and listen on both. This is for Windows Server 2003 and Windows XP SP1.
The preferred modern style (Windows Vista, 7 and 8) is to turn your socket into a dual socket and it will listen to both IPv4 and IPv6. However, your client must also be able to set up a dual socket, so, if your application is serving an old client, you are stuck with the old method.
Thanks!
This is because binding to an IPv6 address does not magically bind to an IPv4 address as well.
On Linux, by default binding to [::] will cause IPv6 and IPv4 to work (unless /proc/sys/net/ipv6/bindv6only is set to 1).
However, on Mac OS X and Windows, binding to [::] will only work for IPv6. You must also bind to an IPv4 address (or 0.0.0.0) for it to work.
Your logic described in your comment "loop through all the results and bind to the first we can" is precisely the problem here. You should both bind to [::] with the IPV6_V6ONLY flag (see setsockopt()) and 0.0.0.0.
Is it because that you bind your server socket to an IPv6 address?
in the "for" loop, IPv6 address appearing before IPv4 address seems to cause your server's socket listen on an IPv6 address.
So your server is not listening on any IPv4 address, cause all connection towards IPv4 address of server is refused.
Try to see all listening port is on which IP address with tool or some command (eg. netstat)
have you tried to run the server and client on the same machine?
this sounds like a firewall problem.
if you succeed connecting telnet / your application on the same machine you'll know this is the problem.
I used two sockets in the same process, one acting as multicast server and the other acting as multicast client. I am trying to combine both server and client functionality in a single socket. Could not succeed till now. Did any one tried making a single socket as multicast server and client. Is it possible? If not any reference that states the limitation would be appreciated. Thank a lot.
It is possible, at least on windows. Try following example(without error checking):
SOCKET the_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("192.168.1.117");
service.sin_port = htons(56565);
int ret = bind(the_socket, (SOCKADDR *) &service, sizeof (service));
unsigned int grpaddr = inet_addr("224.4.4.44");
unsigned int iaddr = inet_addr("192.168.1.117");
//You should have the equivalent function in your existing client
//to join the multicast group
ret = join_source_group(the_socket, grpaddr, service.sin_addr.s_addr, iaddr);
std::string data = "AA";
sockaddr_in group;
group.sin_family = AF_INET;
group.sin_addr.s_addr = inet_addr("224.4.4.44");
group.sin_port = htons(56565);
ret = sendto(the_socket, data.c_str(), data.length(), 0, (const sockaddr*)&group, sizeof(group));
char recvdata[3] = {0};
ret = recv(the_socket, recvdata, 3, 0);
leave_source_group(the_socket, grpaddr, service.sin_addr.s_addr, iaddr);
"Server" and "Client" are not terms which really fit very comfortably into non connection-based sockets. Particularly with multicasting.
So a "Multicast receiver" and "Multicast sender" might be more appropriate.
You can of course, use the same socket to do both at once. It is not mandatory to join a group to send messages to it, but if you do, you may receive your own messages (in some OSs this is optional, for instancce using Linux's setsockopt IP_MULTICAST_LOOP).
"Server" and "client" are really concepts which work at a higher layer than multicasting. I hope that you can explain what you are trying to do better, maybe in another question.
Whether a multicast sender or receiver is the client or server, depends entirely on the application.