So I configured windows 8 firewall to allow IPV6 outbound and inbound connections as a precautionary measure but whenever I try to connect to either are remote host or to my own machine using the loopback address(to an ipv6 server application running simultaneously)the connect function FAILS with error 10049 regardless of what port I choose. Is this a network configuration problem? IP4 works just fine.
#include "stdafx.h"
#include <iostream>
#include <iostream>
#include <string>
#include <stdlib.h>
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <WS2tcpip.h>
#include <ws2ipdef.h>
#include <iphlpapi.h>
#include <IPTypes.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib,"iphlpapi.lib")
using namespace std;
static int MAXPENDING = 5;
void set_interface(SOCKET s, DWORD Index);
int main(int argc,char* argv[])
{
WSADATA wsaData;
int Result;
int optv = 1;
char *optval = (char*)&optv;
int optlen = sizeof(optval);
DWORD Index = 22;
bool connected = false;
string exit = "quit";
string name;
sockaddr_in6 c_addr;
c_addr.sin6_family = AF_INET6;
char buffer[1024];
Result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (Result != NO_ERROR) {
printf("WSAStartup function failed with error: %d\n", GetLastError());
return 0;
}
SETUP:
SOCKET connector;
connector = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (connector == INVALID_SOCKET) {
wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
closesocket(connector);
return 1;
}
cout << "Enter host name(URL): ";
cin >> name;
cout << endl;
char *hostname = const_cast<char*>(name.c_str());
if(inet_pton(AF_INET6,hostname,&c_addr.sin6_addr)<0){
printf("InetPton() function failed with error: %d/n",GetLastError());
closesocket(connector);
return 1;
}
string p;
char *hostport;
int p0rt;
cout << "Enter the port number you wish to connect on: " ;
cin >> p;
cout << endl;
hostport = const_cast<char*>(p.c_str());
p0rt = atoi(hostport);
if(!( 0 < p0rt && p0rt < 65,536)){
cout << "Error: port number must be greater than 0 and less than 65,536. " << endl;
cout << endl;
cout << "Re-enter the port number you wish to connect on: " ;
cin >> p;
cout << endl;
hostport = const_cast<char*>(p.c_str());
p0rt = atoi(hostport);
}else{
c_addr.sin6_port = htons(p0rt);
}
if(connect(connector,(sockaddr*)&c_addr,sizeof(c_addr))<0){
printf("Connect failed with error: %d\n",GetLastError());
string cmd;
cout << endl;
cout <<"Try again? Type 'y' to reattempt connection or type any other key to exit: ";
cin >> cmd;
cout << endl;
if(cmd=="y"){
goto SETUP;
}else {
goto QUIT;
}
}else{
connected = true;
cout << "Connected to host " << hostname << " on port " << c_addr.sin6_port << endl;
cout << "Type 'quit' to exit the program " << endl;
}
while(connected==true){
int nbr = 0;
cout << endl;
cout << ">";
scanf("%s",buffer);
cout << endl;
string str(buffer);
if(str==exit){
connected = false;
goto QUIT;
}
long nbs = send(connector,buffer,sizeof(buffer),0);
if(nbs < 0){
printf("send() failed", GetLastError());
goto QUIT;
}
while(nbr < nbs){
nbr = recv(connector,buffer,sizeof(buffer),0);
if(nbr < 0){
printf("recv() failed", GetLastError());
goto QUIT;
}else if(nbr==0){
printf("recv() failed: connection closed prematurely", GetLastError());
goto QUIT;
}else if(nbr > 0){
cout << endl;
cout << ">> ";
printf(buffer);
cout << endl;
}
}
}
QUIT:
if (closesocket(connector) == SOCKET_ERROR) {
printf("closesocket function failed with error: %ld\n", GetLastError());
WSACleanup();
return 1;
}
WSACleanup();
return 0;
};
void set_interface(SOCKET s, DWORD Index){
MIB_IF_ROW2 T2;
NET_LUID ID;
DWORD ptbuflen = (DWORD)sizeof(T2);
ConvertInterfaceIndexToLuid(Index,&ID);
T2.InterfaceLuid = ID;
GetIfEntry2(&T2);
if(WSAIoctl(s,SIO_ASSOCIATE_HANDLE,&T2,ptbuflen,NULL,0,0,NULL,NULL)>0){
printf("WSAIoctl() function failed with error: %d\n", GetLastError());
closesocket(s);
}
if(WSAIoctl(s,SIO_TRANSLATE_HANDLE,&T2,ptbuflen,NULL,0,0,NULL,NULL)>0){
printf("WSAIoctl() function failed with error: %d\n", GetLastError());
closesocket(s);
}
};
You need to zero out the portion of the sockaddr_in6 that you are not using. Zero out the enire thing first, then fill in the portions you need.
If the user fails to enter a valid port the first time, you are not validating the new port entered the second time, and you are not assigning that second port value to the sockaddr_in6 at all. You should be doing your validation in a loop, and then assign the final accepted value to the sockaddr_in6.
You are using inet_pton() when you should be using getaddrinfo() instead. inet_pton() only converts an IP address string to its binary format. It will not resolve a hostname to an IP. getaddrinfo() does that resolution instead, and it also supports converting IP address strings as well (specify the AI_NUMERICHOST flag in the hints parameter to get that behavior).
Related
I am trying to create a server/client communication console, but once i include the external libraries (cryptopp) and debug, it will always terminate due socket invalid error. I have no idea what is going on.
#include <iostream>
#include <WS2tcpip.h>
#include <string>
#pragma comment (lib, "ws2_32.lib")
#include "../cryptopp565/sha.h"
using CryptoPP::SHA1;
using namespace std;
int main()
{
//initialize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
cerr << "Can't Initialize winsock! program terminate." << endl;
return 1;
}
//create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "Can't create a socket! program terminate." << endl;
return 1;
}
//Promtp to get server port
string server_port_temp;
cout << "Enter port : ";
cin >> server_port_temp;
int server_port = stoi(server_port_temp);
//bind the ip address and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(server_port);
hint.sin_addr.S_un.S_addr = INADDR_ANY;
bind(listening, (sockaddr*)&hint, sizeof(hint));
//tell winsock the socket is for listening
listen(listening, SOMAXCONN);
//wait for connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET)
{
cerr << "Invalid socket ! program terminate." << endl;
return 1;
}
char host[NI_MAXHOST]; //client remote name
char service[NI_MAXHOST]; // service (poet client is connect on)
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXHOST, 0) == 0)
{
cout << host << " Connect on port " << service << endl;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " Connected on port " << ntohs(client.sin_port) << endl;
}
//close listening socket
closesocket(listening);
//while loop: communication
char buf[4096];
//communicate ________________
while (true)
{
ZeroMemory(buf, 4096);
//wait for client to send data
int bytesReceived = recv(clientSocket, buf, 4096, 0);
if (bytesReceived == SOCKET_ERROR)
{
cerr << "Error in recv(). Program terminate." << endl;
break;
}
if (bytesReceived == 0)
{
cout << "Client disconnected " << endl;
break;
}
cout << string(buf, 0, bytesReceived) << endl;
//echo message back to client
send(clientSocket, buf, bytesReceived + 1, 0);
}
//close the socket
closesocket(clientSocket);
//clean winsock
WSACleanup();
system("pause");
return 0;
}`
I wrote a program with a simple pair of client and server,the first of which generate a bunch of strings and sends them via API provided by socket,namely sendmsg(),and the second of which receive the strings with facilitation of epoll.
According to what's captured by the tcpdump and the result of client execution,the client is able to connect to the server and send a few messages correctly,but only a few,the following strings failed to be recieved completely,and at the end of server print of the received codes there is infinite dupilcation of the same string segment.
Please contact me if any more detail is in need.
BTW,is there any recommendation of references which provide detailed description about the usage of sendmsg()?
This is main codes of client:
void MultithreadedLogAnalyzer::SendToServer(string Addr,uint16_t Port) {
int connfd = socket(AF_INET,SOCK_STREAM,0);
sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(Port);
inet_pton(AF_INET,Addr.c_str(),&servaddr.sin_addr);
/*connect failure process to be added*/
int st = connect(connfd,(struct sockaddr *)&servaddr,sizeof(sockaddr));
if(-1 == st){
perror("connection failed");
}
Handle(connfd,servaddr);
close(connfd);
}
void MultithreadedLogAnalyzer::Handle(int connfd,const sockaddr_in &servaddr){
int n= 0,counter =0;
for(vector<string>::iterator si = mFilterResult.begin();si != mFilterResult.end(); ++si)
{
msghdr msg;
iovec iov;
memset(&msg,0,sizeof(msg));
memset(&iov,0,sizeof(iov));
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
char data[1024];
memset(data,0, 1024);
memcpy(data,si->c_str(),si->size());
iov.iov_base = data;
iov.iov_len = (*si).size() ;//check first to locate error
cout << "size:" << (*si).size() << endl;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
//msg.msg_accrights = NULL;
//msg.msg_accrightslen = 0;
n = sendmsg(connfd,&msg,0);
cout << "n: " << n << endl;
++counter;
if (-1 == n)
perror("sendmsg error\n");
}
cout << "number of strings send: " << counter << endl;
The codes of server follows as below:
#include <sys/socket.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <strings.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#define POLLSIZE 100
#define STRINGSIZE 300
using namespace std;
void handle(int fd){
int c = 0;
do{
msghdr msg;
memset(&msg,0,sizeof(msghdr));
msg.msg_name = NULL;
msg.msg_namelen = 0;
char data[1024];
iovec iov;
iov.iov_base = data;
iov.iov_len = 1024;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
c = recvmsg(fd,&msg,0);
if(msg.msg_iovlen==0
){
return;
}
cout << "msg length:" << msg.msg_iovlen<< endl;
cout << string((char *)(msg.msg_iov[0].iov_base)) << endl;
}while(c != -1);
}
int main() {
int listenfd;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in servaddr,cliaddr;
socklen_t socklen = 0;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
int serverPort = 2000;
servaddr.sin_port = htons(serverPort);
bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
int listennumnber = 20;
listen(listenfd,listennumnber);
//the rest to be commented
int epfd = epoll_create(POLLSIZE);
if (epfd < 0)
perror("epoll_create");
struct epoll_event ev;
ev.events = EPOLLIN|EPOLLET;
ev.data.fd = listenfd;
if(epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev) < 0)
perror("epoll_ctl");
int curfds = 1;
struct epoll_event *events = (struct epoll_event*)malloc(sizeof(struct epoll_event));
for (;;){
int n;
int nfds = epoll_wait(epfd,events,curfds,-1);
if (-1 == nfds)
continue;
for(n = 0;n < nfds; ++n){
if(events[n].data.fd == listenfd){
int connfd = accept(listenfd,(struct sockaddr *)&cliaddr ,&socklen);
cout << "connect established through connfd: " << connfd << endl;
if (connfd < 0)
continue;
// if(setnonblocking(connfd) < 0)
// perror("set setnonblocking error");
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = connfd;
if(epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev) < 0)
return -1;
curfds++;
continue;
}
handle(events[n].data.fd);
}
}
return 0;
}
Problem solved by adding send() and recv() functions in appropriate places of the message transferring loop.
cout << "msg length:" << msg.msg_iovlen<< endl;
cout << string((char *)(msg.msg_iov[0].iov_base)) << endl;
This message should only print msg.msg_iov[0].iov_len bytes.
}while(c != -1);
This is in the wrong place. It should be a test immediately after c = recvmsg(...); it should be if (c > 0), and if c == -1 you should either call perror() or use errno or strerror() in a message, immediately, without calling any other system calls.
Basically you're continuing to receive beyond end of stream; you're printing junk after end of stream or an error; and you're ignoring the actual message length when printing the message.
I have a simple udp application written using boost:asio, where udp unicast receiver runs on windows and unicast sender runs on linux . My unicast sender on linux sent the packet successfully , but reciver on windows does not any packets , but I could see that packets sent by sender on wireshark which is running on windows . below is my udp receiver code (which is based on the sample provided my boost libs).
class unicast_Receiver
{
public:
unicast_Receiver(boost::asio::io_service& io_service, boost::asio::ip::udp::endpoint end1)
: socket_(io_service)
{
socket_.open(boost::asio::ip::udp::v4());
//socket_.open(end1.protocol());
socket_.bind(end1);
socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
std::cout << " >> on " <<socket_.local_endpoint()<<" :: #" << __LINE__ << __FUNCTION__ <<std::endl;
start_receive();
}
private:
void start_receive()
{
std::cout << "\n !!!!Waiting in the Unicast Data Receive >> on " << Unicastlisten_endpoint_ <<" :: #" << __LINE__ << __FUNCTION__ <<std::endl;
socket_.async_receive_from(
boost::asio::buffer(data_, max_length), remote_endpoint_,
boost::bind(&unicast_Receiver::handle_receive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void handle_receive(const boost::system::error_code& error,
std::size_t /*bytes_transferred*/)
{
if (!error || error == boost::asio::error::message_size)
{
std::cout << "Unicast Data Received >> " <<"<< #" << __LINE__ << __FUNCTION__ <<std::endl;
std::cout << "\n" << data_ << "\n";
memset(data_,0,max_length);
start_receive();
}
}
void handle_send(boost::shared_ptr<std::string> /*message*/,
const boost::system::error_code& /*error*/,
std::size_t /*bytes_transferred*/)
{
}
udp::socket socket_;
udp::endpoint remote_endpoint_;
enum { max_length = 1024 };
char data_[max_length];
boost::array<char, 1> recv_buffer_;
};
int main(int argc, char* argv[])
{
boost::asio::io_service io_serviceSe;
boost::asio::ip::udp::endpoint Unicastlisten_endpoint_(boost::asio::ip::address::from_string(argv[1]),atoi(argv[2]));
unicast_Receiver server(io_serviceSe,Unicastlisten_endpoint_);
}
There is the code i am trying to implement in a client/server model but segmentation fault error is coming..
server:
/* this is the structure i am trying to pass*/
struct pkt{
char data[1000];
int seqNo;
int checksum;
void make_pkt(int seq,char dat[1000],int check)
{
seqNo=seq;
strcpy(data,dat);
checksum=check;
}
};
the main part is
main() /* main */
{
port=client_addr.sin_port;
cout<<"port : "<<port;
pkt *rcv=new pkt;
do{
cout<<"a"<<endl;
cout<<"port : "<<port;
pkt *newpkt=new pkt;
char *buffer=new char [1000];
strcpy(buffer,"Hamza");
newpkt->make_pkt(1,buffer,2);
cout<<"aa"<<endl;
client_addr.sin_port=port;
cout<<"port 2 : "<<client_addr.sin_port<<endl;
sendto(sockfd,&newpkt,sizeof(struct pkt),0,(struct sockaddr *) &client_addr,sizeof(client_addr));
cout<<"aaa"<<endl;
recvfrom(sockfd,&rcv,sizeof(struct pkt),0,(struct sockaddr *)&client_addr,&leng);
cout<<"bb :"<<rcv->seqNo<<endl;
}while(rcv->seqNo!=1);
}
client:
struct pkt{
char data[1000];
int seqNo;
int checksum;
pkt()
{
strcpy(data," ");
seqNo=0;
timer=0;
checksum=0;
}
};
main()
{
pkt *newpkt=new pkt;
do{
cout<<"aa"<<endl;
pkt *rcvpkt=new pkt;
socklen_t lengt=sizeof(my_addr);
recvfrom(sockfd,&rcvpkt,sizeof(struct pkt),0,(struct sockaddr *)&my_addr,&lengt);
cout<<"aaa"<<endl;
cout<<"aaa"<<rcvpkt->data<<endl;
newpkt->seqNo=1;
sendto(sockfd,&newpkt,sizeof(struct pkt),0,(struct sockaddr *) &my_addr,sizeof(my_addr));
}while(newpkt->seqNo!=1);
}
please tell me whats the problem in this code..?
You are not passing the struct instances to sendto() and recvfrom() correctly. Your pkt variables are pointers so you need to get rid of the & operator when passing them. You also have memory leaks. Try this instead:
main()
{
port = ntohs(client_addr.sin_port);
cout << "port : " << port;
pkt *rcv = new pkt;
do{
cout << "a" << endl;
cout << "port : " << port;
pkt *newpkt = new pkt;
char buffer[1000];
strcpy(buffer,"Hamza");
newpkt->make_pkt(1,buffer,2);
cout << "aa" << endl;
client_addr.sin_port = htons(port);
cout << "port 2 : " << ntohs(client_addr.sin_port) << endl;
sendto(sockfd, newpkt, sizeof(struct pkt), 0, (struct sockaddr *) &client_addr, sizeof(client_addr));
delete newpkt;
cout << "aaa" << endl;
recvfrom(sockfd, rcv, sizeof(struct pkt), 0, (struct sockaddr *)&client_addr, &leng);
cout << "bb :" << rcv->seqNo << endl;
}
while(rcv->seqNo != 1);
delete rcv;
}
main()
{
pkt *newpkt = new pkt;
do{
cout << "aa" << endl;
pkt *rcvpkt = new pkt;
socklen_t lengt = sizeof(my_addr);
recvfrom(sockfd, rcvpkt, sizeof(struct pkt), 0, (struct sockaddr *)&my_addr, &lengt);
cout << "aaa" << endl;
cout << "aaa" << rcvpkt->data << endl;
newpkt->seqNo = 1;
sendto(sockfd, newpkt, sizeof(struct pkt), 0, (struct sockaddr *) &my_addr, sizeof(my_addr));
delete rcvpkt;
}
while(newpkt->seqNo != 1);
delete newpkt;
}
I'm trying to port my IRC bot from Python to C++ and I'm running into some issues with Winsock2. I'm fairly new to sockets in C/C++ and most of this code was pieced together from various tutorials. I keep getting error 10049 and am at a loss. Any help would be appreciated greatly. Thanks!
port_ is set to 6667 and host_ is "irc.rizon.net"
WSADATA wsaData;
int starterr = WSAStartup(MAKEWORD(2,2), &wsaData);
if (starterr != 0) {
std::cout << "Error: " << WSAGetLastError() << " occurred!" << std::endl;
WSACleanup();
return 1;
}
std::cout << "WSAStartup Successful!" << std::endl;
socketfd_ = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (socketfd_ == INVALID_SOCKET) {
std::cout << "Error: " << WSAGetLastError() << " occurred!" << std::endl;
WSACleanup();
return 1;
}
std::cout << "Socket Creation Successful!" << std::endl;
sockaddr_in anews;
anews.sin_port = htons(port_);
anews.sin_addr.s_addr = inet_addr(host_.c_str());
anews.sin_family = AF_INET;
if (connect(socketfd_,(sockaddr*)&anews, sizeof(anews)) == SOCKET_ERROR) {
std::cout << "Error: " << WSAGetLastError() << " occurred!" << std::endl;
WSACleanup();
return 1;
}
std::cout << "Socket has connected successfuly!" << std::endl;
return 0;
inet_addr() takes a dotted IP address of the form "x.x.x.x" you are passing it the host name.
You can use gethostbyname():
hostent* host;
char* ip;
...
// Get the local host information
host= gethostbyname(host_.c_str());
ip= inet_ntoa(*(struct in_addr *)*host->h_addr_list);
sockaddr_in anews;
anews.sin_port = htons(port_);
anews.sin_addr.s_addr = inet_addr(ip);
anews.sin_family = AF_INET;
...
Or an easier route would be to use getaddrinfo():
struct addrinfo *ai;
if(getaddrinfo(host_.c_str(), "6667", NULL, &ai) != 0)
return 1;
socketfd_ = socket(ai->ai_family, SOCK_STREAM, 0);
if (socketfd_ == INVALID_SOCKET) {
freeaddrinfo(ai);
return 1
}
if (connect(socketfd_, ai->ai_addr, (int)ai->ai_addrlen) == SOCKET_ERROR) {
closesocket(socketfd_);
freeaddrinfo(ai);
return 1;
}
...