Firstly, the code I will share is the basis of my code(found it in another site, open source), I added functions and threads later to improve.
In the office, we have local network and another 3 computer cannot connect to my server. Especially have a look at that line. 26010 is random port number that I want to listen. According to data I found in the other topics, NULL and 127.0.0.1 are the localhost ip.I tried my own ip number instead of NULL, but it didn't work. I can send data from my client code to other computers, but can't get any connections.
Code is listening connections properly, and can get info if I open another 3 terminal and try to connect it from my computer through my client code. How to fix that?
Thanks in advance.
status = getaddrinfo(NULL, "26010", &host_info, &host_info_list);
int main()
{
int status;
struct addrinfo host_info; // The struct that getaddrinfo() fills up with data.
struct addrinfo *host_info_list; // Pointer to the to the linked list of host_info's.
memset(&host_info, 0, sizeof host_info);
std::cout << "Setting up the structs..." << std::endl;
host_info.ai_family = AF_UNSPEC; // IP version not specified. Can be both.
host_info.ai_socktype = SOCK_STREAM; // Use SOCK_STREAM for TCP or SOCK_DGRAM for UDP.
host_info.ai_flags = AI_PASSIVE;
**status = getaddrinfo(NULL, "26010", &host_info, &host_info_list);**
// getaddrinfo returns 0 on succes, or some other value when an error occured.
// (translated into human readable text by the gai_gai_strerror function).
if (status != 0) std::cout << "getaddrinfo error" << gai_strerror(status) ;
std::cout << "Creating a socket..." << std::endl;
int socketfd ; // The socket descripter
socketfd = socket(host_info_list->ai_family, host_info_list->ai_socktype,
host_info_list->ai_protocol);
if (socketfd == -1) std::cout << "socket error " ;
std::cout << "Binding socket..." << std::endl;
int yes = 1;
status = setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
status = bind(socketfd, host_info_list->ai_addr, host_info_list->ai_addrlen);
if (status == -1) std::cout << "bind error" << std::endl ;
std::cout << "Listen()ing for connections..." << std::endl;
status = listen(socketfd, 5);
if (status == -1) std::cout << "listen error" << std::endl ;
int new_sd;
struct sockaddr_storage their_addr;
socklen_t addr_size = sizeof(their_addr);
new_sd = accept(socketfd, (struct sockaddr *)&their_addr, &addr_size);
if (new_sd == -1)
{
std::cout << "listen error" << std::endl ;
}
else
{
std::cout << "Connection accepted. Using new socketfd : " << new_sd << std::endl;
}
std::cout << "Waiting to recieve data..." << std::endl;
ssize_t bytes_recieved;
char incomming_data_buffer[1000];
bytes_recieved = recv(new_sd, incomming_data_buffer,1000, 0);
// If no data arrives, the program will just wait here until some data arrives.
...
std::cout << "send()ing back a message..." << std::endl;
return 0 ;
}
Your problem is your call to getaddrinfo(). This function returns information in the host_info_list member. What you're reading is the hint (host_info) which is not changed by getaddrinfo(). You would need to use host_info_list to read the what's returned by getaddrinfo. You never use it and you never free it (by calling freeaddrinfo).
I am not sure why you'd want to use getaddrinfo() to listen for connection. You can just build the sockaddr yourself. It's easy:
struct sockaddr_in listenAddr;
memset(&listenAddr, 0, sizeof(listenAddr));
/* IPv4 address */
listenAddr.sin_family = AF_INET;
/* your port number */
listenAddr.sin_port = htons(26010);
/* listen on all interfaces */
listenAddr.sin_addr.s_addr = htonl(INADDR_ANY);
/* TCP socket */
socketfd = socket(PF_INET, SOCK_STREAM, 0);
/* your error code, omitted here */
status = bind(SocketFD,(struct sockaddr *) &listenAddr, sizeof(listenAddr))
Related
I'm trying to make a winsock server and I want to display the client's ip on the server when he connects but that's where there is a problem. Every time I try to connect it display 204.204.204.204. I tried to connect with another computer but the result was the same.
result in localhost
After this, I started looking for people having the same problem as me on this website and I found several people who had the same as me but they all had either the accept or the inet_ntop function that wasn't working correctly. So I check and none of this two functions return an error. Maybe I'm stupid but I really can't figured out what's the problem. (btw english is not my first language so please tell me if you noticed or if my english isn't too bad)
the part of the code that isn't working
sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&client, &clientlen);
if (client == INVALID_SOCKET)
{
std::cout << "Error in accept(): " << WSAGetLastError << std::endl;
WSACleanup();
}
else
{
char clientIp[17];
if (inet_ntop(AF_INET, &from.sin_addr, clientIp, 17) == NULL)
{
std::cout << "Can't get the client's ip: " << WSAGetLastError() << std::endl;
}
std::cout << "ip connected: " << clientIp << std::endl;
the whole code if you need it
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string>
#pragma comment(lib, "ws2_32.lib")
int main()
{
std::cout << "--- Tcp/ip Server ---" << std::endl;
WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa);
SOCKET server = socket(AF_INET, SOCK_STREAM, 0);
if (server == INVALID_SOCKET)
{
std::cout << "error in SOCKET(): "<< WSAGetLastError() << std::endl;
WSACleanup();
}
sockaddr_in s;
s.sin_family = AF_INET;
s.sin_addr.s_addr = INADDR_ANY;
s.sin_port = htons(52000);
// bind
if (bind(server, (sockaddr*)&s, sizeof(s)) == SOCKET_ERROR)
{
std::cout << "Error: bind()" << std::endl;
}
//listen
if (listen(server, SOMAXCONN) == SOCKET_ERROR)
{
std::cout << "Error in listen(): " << WSAGetLastError() << std::endl;
WSACleanup();
}
sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&client, &clientlen);
if (client == INVALID_SOCKET)
{
std::cout << "Error in accept(): " << WSAGetLastError << std::endl;
WSACleanup();
}
else
{
char clientIp[17];
if (inet_ntop(AF_INET, &from.sin_addr, clientIp, 17) == NULL)
{
std::cout << "Can't get the client's ip: " << WSAGetLastError() << std::endl;
}
std::cout << "ip connected: " << clientIp << std::endl;
// the code isn't finished yet
system("pause");
WSACleanup();
}
return 0;
}
You are passing the address of the wrong variable in the second parameter of accept().
You are passing the address of your SOCKET client variable that you are about to assign the result of accept() to. C++ allows a variable's address to be taken when declaring and initializing the variable in the same statement. But that is not what you want in this case. You need to pass the address of your sockaddr_in from variable instead:
sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&from, &clientlen); // <-- &from instead of &client
You are leaving your from variable uninitialized, and your compiler fills uninitialized variables with 0xCC (decimal 204) bytes in debug mode, so that is why you end up seeing 204.204.204.204 (hex 0xCC 0xCC 0xCC 0xCC) from inet_ntop() when you don't initialize your from variable properly.
I have a problem with my C++ networking code(a test server that receives strings and displays it). Occasionally, when I turn off my server(Ctrl C) and then restart it, clients fail to connect to it. If I wait for around a minute and try connecting with a client again, it works perfect. Doing a ps -A | grep my_server I don't find the process running. However, if I'd try to connect in about 2 minutes it would work just fine.
I find this rather strange.
I'm used to a slightly similar problem in Python, where I have trouble connecting to a port after pressing Ctrl+C. In that case, the process might still be running and I'd have to manually kill the process and try connecting again(and it would work just fine then).
Is there any code that you'd like me to paste in particular? I'm accepting the connections as follows :-
NetworkManager* start_listening(char* host, int port) {
keep_running = true;
signal(SIGINT, signal_handler);
int listenfd, connfd, n;
struct sockaddr_in servaddr, cliaddr;
socklen_t clilen;
pid_t pid;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
#ifdef DEBUG
std::cout << "[+] Starting to listen at port " << port << std::endl;
#endif
#ifdef DEBUG
std::cout << "[+] Binding to port" << std::endl;
#endif
bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
#ifdef DEBUG
std::cout << "[+] Starting to listen" << std::endl;
#endif
listen(listenfd, 1024);
clilen = sizeof(cliaddr);
while ( keep_running ) {
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
#ifdef DEBUG
if ( connfd == -1 ) {
std::cout << "Yikes got an error with errno = " << errno << std::endl;
}
sockaddr_in* pV4Addr = (struct sockaddr_in*)&cliaddr;
int ipAddr = pV4Addr->sin_addr.s_addr;
char str[20];
inet_ntop(AF_INET, &ipAddr, str, 20);
std::cout << "[+] Incoming connection from " << str << std::endl;
std::cout << "[+] Using socket " << connfd << std::endl;
#endif
if ( (pid=fork()) == 0 ) {
close(listenfd);
NetworkManager *nm = new NetworkManager(connfd);
return nm;
} else {
close(connfd);
}
}
if (!keep_running) {
// #TODO kill all children
#ifdef DEBUG
std::cout << "[+] Killing server" << std::endl;
#endif
exit(0);
}
return 0;
}
The problem is that you're not checking your return values. For example, to bind. Which could be failing. For example, because you aren't using REUSEADDR to allow binding to a port which was recently in use. There's a timeout on these things, and that was a dead giveaway when you mentioned that it works again after two minutes. But really, check your return values--this is C after all!
I made a simple client program who connect to server via port 80;
int v=connect(mysocket,(struct sockaddr *)&server,sizeof(server));
if(v==SOCKET_ERROR){
cout<<"error connecting to server";
}
if (v==0) cout<<"connected"<<endl;
its says connect return 0 if success.
but i get the error;
can you please tell me when i must use htonl or htons i used only server.sin_port=htons(80);
should i use server.sin_addr.s_addr=inet_addr("someip_ignorethis"); or i must use
server.sin_addr.s_addr=htonl(inet_addr("someip_ignorethis"));
what is the problem WHY AND WHEN i need to use host to network conversation,how does it make my program portable???.
what socket i must use? socket version 2,2?
THNAKS FOR THE HELP!
I get 10038 ERROR HELP FIX MY CODE pastebin.com/4pdqsGqW
If you had bothered to use your debugger and debug the code yourself, you would have found that your mySocket variable is always 0, because you are not initializing it correctly.
This line:
if (mysocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)==INVALID_SOCKET){
Is effectively the same as this:
if (mysocket=(socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)==INVALID_SOCKET)){
If socket() succeeds, ==INVALID_SOCKET evaluates as false, so 0 is assigned to mysocket. Read up on Operator Precedence. The == operator has a higher precedence than the = operator.
To fix it, change that line to this instead:
if ((mysocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){
Or better, get out of the habit of assigning and comparing a variable in the same statement:
mysocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (mysocket==INVALID_SOCKET){
Also, if you had bothered to pay attention to your compiler's output messages, you would have seen that your "CONNECTED!" message is code that is never reached, because it is inside the curly braces for when connect() fails, but there is a return before you print the message.
Try this code instead:
#include <winsock2.h>
#include <iostream.h>
#include <windows.h>
//#define portnumber 80
using namespace std;
//Winsock Library
int main(int argc, char* argv[])
{
WSADATA ws = {0};
int v = WSAStartup(MAKEWORD(2,2), &ws);
if (v != 0)
{
cout << "error initialising winsock: " << v << endl;
getchar();
return 1;
}
cout << "winsock started" << endl;
SOCKET mysocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (mysocket == INVALID_SOCKET)
{
cout << "error creating socket: " << WSAGetLastError() << endl;
getchar();
return 1;
}
cout << "socket created" << endl;
struct sockaddr_in server = {0};
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("84.95.234.174");
//cout << inet_ntoa(server.sin_addr) << endl;
server.sin_port = htons(80);
if (connect(mysocket, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
cout << "error connecting to server: " << WSAGetLastError() << endl;
getchar();
return 1;
}
cout << "CONNECTED!" << endl;
getchar();
closesocket(mysocket);
return 0;
}
10038 is WSAENOTSOCK. Clearly the value of socket is invalid.
You should have found all that out for yourself before you posted, and looked up what the error meant as well.
Personally, I use this and it never fails me..
struct addrinfo *it = nullptr, *result = nullptr;
getaddrinfo(Address.c_str(), nullptr, nullptr, &result);
for (it = result; it != nullptr; it = it->ai_next)
{
sockaddr_ipv4 = reinterpret_cast<sockaddr_in*>(it->ai_addr);
Address = inet_ntoa(sockaddr_ipv4->sin_addr);
if (Address != "0.0.0.0") break;
}
freeaddrinfo(result);
And I use:
struct sockaddr_in SockAddr;
memset(&SockAddr, 0, sizeof(SockAddr));
SockAddr.sin_port = htons(Port);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = Address == "INADDR_ANY" ? htonl(INADDR_ANY) : inet_addr(Address.c_str());
if (connect(socket, reinterpret_cast<SOCKADDR*>(&SockAddr), sizeof(SockAddr)) == SOCKET_ERROR)
{
//print error.. clean up..
}
What it does is it checks the address. If it is INADDR_ANY, then it will use htonl. If not, it uses inet_addr to convert the address into an IP. Htonl on the other hand just converts the address into network byte order.
I am currently programming a C++ module that creates a socket server thread, which polls the accept() function every 1ms. I have a test module that spoofs a client connection that is also running. The test module initiates the creation of the server thread. After the thread is created and verified to be running, the client runs the connect() command as a test. My code states that a connection was established, returning a 0 on the connect command. However, the accept() running in my server thread never receives the connection.
The server is bound to accepting any IP:50000, and the client is not bound, but has 127.0.0.1:50000 set as its destination. Is my Linux environment automatically accepting this connection?
Here is the code for my server's socket:
int nSocket;
int nOn = 1;
int nControl;
struct sockaddr_in sServerAddress;
nSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(nSocket < 0)
{
std::cout << "Failed to create socket\n";
}
if(setsockopt(nSocket, SOL_SOCKET, SO_REUSEADDR, &nOn, sizeof(int)) < 0)
{
std::cout << "failed to set socket option\n";
}
nControl = fcntl(nSocket, F_GETFL);
if(fcntl(nSocket, F_SETFL, O_NONBLOCK | nControl) < 0)
{
std::cout << "set not blocking failed\n";
}
memset(&sServerAddress, 0x00, sizeof(struct sockaddr_in));
sServerAddress.sin_family = AF_INET;
sServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
sServerAddress.sin_port = htons(mtListenPort);
if(bind(nSocket, (struct sockaddr*)&sServerAddress, sizeof(struct sockaddr_in)) < 0)
{
std::cout << errno << "bind failed\n";
}
if(listen(nSocket, MAXPENDING) < 0)
{
std::cout << "listen failed\n";
}
Here is the code for my test client's socket:
int nSocket;
nSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(nSocket < 0)
{
std::cout << "Failed to create socket\n";
}
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
inet_aton(LOCAL_HOST, &serverAddress.sin_addr);
serverAddress.sin_port = htons(LISTEN_PORT00);
char msg[] = "Hello World.";
usleep(10000);
if (connect(nSocket, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0)
{
std::cout << errno << "Could not connect to the server.\n";
}
usleep(10000);
if (sendto(nSocket, msg, strlen(msg), 0, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0)
{
std::cout << errno << "Could not send data to the server.\n";
}
Here is a small part of the thread that runs the accept code.
while(mbListening)
{
nMessengerSocket = accept(mnSocket, (struct sockaddr*)&sClientAddr, &tClientAddrLength);
if(nMessengerSocket >= 0)
{
std::cout << "Accepted connection from " << inet_ntoa(sClientAddr.sin_addr) << std::endl;
mnConnections++;
mbListening = false;
}
mThreadRunningTime++;
usleep(1000);
}
Make sure tClientAddrLength is initialized to sizeof sClientAddr before calling accept(). That is a common error.
Don't silently ignore errors. Examine the error code in errno because it tells you what went wrong.
Are you using sendto? That's for UDP... Use send.
Also, check if the port is free:
telnet localhost 50000
netstat -a
I'm currently having a problem passing messages between a server and client.
As far as I know, I am properly following best practices for socket programming outlined by Beej's Socket Programming Tutorial.
When I run the two processes, the recv() syscall returns -1 (an error), rather than the number of bytes received. Also when trying to output the buf, there are a bunch of gobbledygook characters. Which makes sense, because of the error.
I'm wondering if someone could steer me in the right direction as to why I am having issues with recv()? The following are relevant code snippets.
Server:
struct sockaddr_storage their_addr;
socklen_t addr_size;
int sockfd, newfd, byte_count, status;
char buf[512];
struct addrinfo hints, *res;
// first, load up address structs with getaddrinfo():
memset(&hints, 0, sizeof hints);
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// get address info, print stuff if error
if((status = getaddrinfo("nunki.usc.edu", "21957", &hints, &res)) !=0){
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
// make a socket:
if((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1){
cout << "socket fail" << endl;
}
// bind the socket to the port
bind(sockfd, res->ai_addr, res->ai_addrlen);
// required output
cout << "Phase1: Login server has TCP port number " << "21957 "
<< "and IP address " << getIPfromHost("nunki.usc.edu") << endl;
// listen for incoming connections
listen(sockfd, 10);
cout << "after listen" << endl;
// halt until receipt
addr_size = sizeof(their_addr);
newfd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size);
cout << "after accept" << endl;
// Now that we're connected, we can receive some data
byte_count = recv(sockfd, buf, sizeof buf, 0);
printf("recv()'d %d bytes of data in buf\n", byte_count);
printf("Msg is %s\n", buf);
Client:
struct addrinfo hints, *res;
int sockfd;
// first, load up address structs with getaddrinfo():
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("nunki.usc.edu", "21957", &hints, &res);
// make a socket:
if((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1){
cout << "socket fail" << endl;
}
// attempt connection to port
if(connect(sockfd, res->ai_addr, res->ai_addrlen) == -1){
cout << "connect fail" << endl;
}
// send message to server
cout << "sockfd " << sockfd << endl;
int byte_count = send(sockfd, "Hello", 5, 0);
cout << byte_count << endl;
The following is the output for Server:
Phase1: Login server has TCP port number 21957 and IP address 68.181.201.3
after listen
after accept
recv()'d -1 bytes of data in buf
Msg is ÿhÿ?sÈ
Glæ
The following is the output for Client:
sockfd 4
5
You are calling recv on the wrong socket. You need to recv on newfd:
byte_count = recv(newfd, buf, sizeof buf, 0); /* newfd instead of sockfd. */
Now that that's out of the way,
As far as I know, I am properly following best practices for socket
programming
I completely disagree.
You are not checking return statuses for listen, bind, getaddrinfo etc
There's not strerror or perror in your program
You want to recv() using the socket returned from accept()
byte_count = recv(newfd, buf, sizeof buf, 0);
Maybe I shouldn't write this as an answer, but as a comment. Nevertheless, IMHO your use of getaddrinfo() seems wrong to me.
On the client side, it is supposed to be called and then iterated through the results until a connection can be established.
so
struct addrinfo * r2
sockfd = -1;
for (r2=res; r2; r2=r2->ai_next) {
// make a socket:
if((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1){
continue; // next result
}
// attempt connection to port
if(connect(sockfd, res->ai_addr, res->ai_addrlen) == -1){
close(sockfd);
sockfd = -1;
continue;
}
}
if (sockfd == -1) {
// do error handling
}
In this way, you can check all possible connections.
On the server side, it is rather unusual to use getaddrinfo(). Normally, you would create an IPv6 socket and enable it to listen for IPv4 as well by using setsockopt() to unset the IPV6_V6ONLY flag. In this way, the socket listens to both IPv6 and IPv4. (Alas, not on WIndows XP AFAIK.)
The sockfd is just useed for listening the clients, newfd is used for data transmitting.