I have a very simple socket client program that I want to use to ping my mail server (as an example) to make sure it's alive and responding. I am using the following code to connect:
portno=25;
sockfd=socket(AF_INET,SOCK_STREAM,0);
if (sockfd<0) error("Cannot open socket");
server=gethostbyname(argv[2]);
if (server==NULL) {
printf("Error: No such host exists\n");
exit(3);
}
bzero((char*)&srvr,sizeof(srvr));
srvr.sin_family=AF_INET;
bcopy((char*)&server->h_addr,(char*)&srvr.sin_addr.s_addr,server->h_length);
srvr.sin_port=htons(portno);
if (connect(sockfd,(struct sockaddr*)&srvr,sizeof(srvr)) <0) error("Error connecting");
I pass the server name (as localhost) on the command line as the second parameter. It always hangs in the connect call. I have tried to also connect to one of google's mail servers with the same result.
I am able to telnet into port 25 on both my local server and the google server and issue the HELO command and get a response. I am running the program as root.
I am unsure how to proceed further in order to determine the problem. Any help would be appreciated.
The code is apparently not complete. You might want to make a couple of debug messaging including a check for the correct input to gethostbyname().
You should normally use IPPROTO_TCP as protocol, instead of 0.
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
You might want to use a tool like strace to see more details about how the system calls went on.
It's usually better to use getaddrinfo().
const char *node = "www.fedoraproject.org";
const char *service = "http";
struct addrinfo hints = {
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
.ai_protocol = IPPROTO_TCP,
.ai_flags = AI_ADDRCONFIG,
.ai_canonname = NULL,
.ai_addr = NULL,
.ai_next = NULL
};
struct addrinfo *result;
int error;
error = getaddrinfo(node, service, &hints, &result);
struct addrinfo *item;
int sock;
for (item = result; item; item = item->ai_next) {
sock = socket(item->ai_family, item->ai_socktype, item->ai_protocol);
if (sock == -1)
continue;
if (connect(sock, item->ai_addr, item->ai_addrlen) != -1) {
fprintf(stderr, "Connected successfully.");
break;
}
close(sock);
}
freeaddrinfo(result);
See: https://fedoraproject.org/wiki/Networking/NameResolution#Connecting_to_services_using_getaddrinfo.28.29
Related
There are some other questions related to this, but they are not solving my problem. So I am asking so that some other possible solution can be seen.
I am implementing the socket programming. Socket is being successfully created, and it connects successfully to localhost. But when I choose some remote server, then it gives the error 10061 and sometimes 10060. I tried many remote servers(for example: google.com and my company hostname also).
I checked the firewall it is OFF. my code is given below:
/*
Socket Programming on Windows Machine
Author : Raza Javed
Date : 11-10-2022
*/
#include<stdio.h>
#include<winsock2.h>
#include<string.h>
int main(int argc, char *argv[])
{
// Winsock Initialization
WSADATA wsa; // WSADATA is the structure that holds the information about Winsock library
SOCKET s;
struct sockaddr_in server;
struct in_addr **addr_list;
struct hostent *he;
char *hostname = "localhost";
char ip[100];
printf("Initializing Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa)!=0)
{
printf("Failed. Error Code : %d", WSAGetLastError()); //WSAGetLastError is used to get more information about what error occured.
return 1;
}
printf("Initialized.\n");
// Socket Creation
if((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
printf("Could not create the socket: %d", WSAGetLastError());
}
printf("Socket Created.\n");
// Getting IP using "gethostbyname"
if ((he = gethostbyname(hostname)) == NULL)
{
printf("gethostbyname failed : %d", WSAGetLastError());
return 1;
}
addr_list = (struct in_addr **)he -> h_addr_list; // Casting h_addr_list to in_addr
for(int i = 0; addr_list[i] != NULL; i++)
{
strcpy(ip, inet_ntoa(*addr_list[i]));
}
printf("%s resolved to %s\n", hostname, ip);
// Connecting to server
//memset(&server, "\0", sizeof(server));
server.sin_addr.s_addr = inet_addr(ip);
server.sin_family = AF_INET;
server.sin_port = htons(49835);
if (connect(s, (struct sockaddr *)&server, sizeof(server)) < 0)
{
printf("connect error : %d", WSAGetLastError());
getchar();
return 1;
}
puts("connected");
getchar(); // To hold the terminal screen
return 0;
}
Listening port can be seen here:
TCP 127.0.0.1:49835 0.0.0.0:0 LISTENING
In case of localhost, I get the following output:
Initializing Winsock...Initialized.
Socket Created.
localhost resolved to 127.0.0.1
connected
But when I change it to some remote server for example google like below:
char *hostname = "www.google.com";
Then the output is:
Initializing Winsock...Initialized.
Socket Created.
www.google.com resolved to 142.251.209.132
connect error : 10060
Can someone please help in this. I am completely not getting it.
I found the solution myself. maybe it would be helpful for someone else.
The mistake I was doing is that I have been always using the 'wrong port' to connect. To connect to remote server for example www.google.com, the port number will be 80, so the line of the code above will be:
server.sin_port = htons(80);
because it is for HTTP connection.
just by changing the line like above. It is connected now. Results below:
Initializing Winsock...Initialized.
Socket Created.
www.google.com resolved to 142.250.186.100
connected
I am exploring network programming in C.The code is supposed to connect to a server on port 80 send an http request and from the response print on what server is the web page running on, but it runs into Invalid Argument error. The error occurs with error message "[ERR] connecting to target server: Invalid argument" so the error should be somewhere in the connect() function.
rec = connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr) == -1);
if(rec == -1)
fail("[ERR] connecting to target server");
Although I have seen a lot of similar issues, none of the fixes neither worked or applied to this case, strangely this code works as a standalone program when parsing argc[1] instead of char *name, regardless of what the exact string literal is(ip or hostname, experimented with multiple for both). The only difference between the two being that the entire web server function is written in main and passed command-line arguments(working example) while here it is written as a standalone function and called in main where it was tested on a few web page names and IP addresses.
Any help would be appreciated as I feel this might be some simple mistake I overlooked or something I don't understand well enough. Thanks!
int web_server(char *name){
int sockfd, rec;
struct hostent *host_info;
//struct in_addr *address;
struct sockaddr_in target_addr;
unsigned char buffer[4096];
if(is_ip(name)){
target_addr.sin_addr.s_addr = inet_addr(name);
} else if(host_info = gethostbyname(name)){
if(host_info == NULL){
fail("[ERR] looking up hostname!");
}else{
target_addr.sin_addr = *((struct in_addr *) host_info -> h_addr);
}
} else{
fail("[ERR] getting address");
}
target_addr.sin_family = AF_INET;
target_addr.sin_port = htons(80);
memset(&(target_addr.sin_zero), 0, 8);
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd == -1){
fail("[ERR] in socket");
}
rec = connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr) == -1);
if(rec == -1)
fail("[ERR] connecting to target server");
send_string(sockfd, "HEAD / HTTP/1.0\r\n\r\n");
while(recv_line(sockfd, buffer)){
if(strncasecmp(buffer, "Server: ", 7) == 0){
printf("The web server for %s is %s\n", name, buffer+8);
}
}
close(sockfd);
printf("Server line not found\n");
exit(1);
}
int main(){
web_server("127.0.0.1");//doesn't work with hostnames either
}
I'm coding a C application to connect with a router. The router does not filter any incoming connections, neither is behind any firewall. My problem is the C function "connect" returns SOCKET_ERROR, but the error message I get calling perror when this happens is: No error (¿?). That probably means I'm looking in the wrong direction (the place where perror gets the error msg from is not the place I'm interested in).
UPDATE: As suggested in comments, I called WSAGetLastError(), which returns 10061 (connection refused)
At same time, I have a web application that connects with the router and send it a json message via AJAX call. No problem at all. Using the same IP and same port to connect with.
If helps, the connect function I'm using is defined at WinSock2.h. Working with Windows 7 Home Premium and Visual Studio 2010.
Those are what I consider relevant parts of the code (UPDATE: Added the missing part of socket initialization)
// Enters here
#ifdef WIN32
WSADATA wsaData;
int error = WSAStartup(MAKEWORD(2,0), &wsaData);
if(error != 0) return false;
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0)
{
WSACleanup();
return false;
}
#endif
struct addrinfo hints;
struct addrinfo *m_data;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_socktype = SOCK_STREAM;
// hostname is a char * containing my IP, in the same subnetwork than the router,
// and I'm going to connect with 192.168.90.1 (connection correctly open) and port 5555
port = "5555";
getaddrinfo(hostname, port, &hints, &m_data);
int m_socket = socket(m_data->ai_family, m_data->ai_socktype, m_data->ai_protocol);
// more stuff here
if (connect(m_socket, (struct sockaddr *)m_data->ai_addr, m_data->ai_addrlen) == SOCKET_ERROR)
{
// I get "connection error: no error" here. Why?
perror("connection error");
closesocket(m_socket);
return false;
}
So, why can I connect via AJAX call but the C connect function returns SOCKET_ERROR? Any clues?
Many thanks in advance
You forgot to set the protocol.
hints.ai_protocol = IPPROTO_TCP;
And also, you should try initializing Winsock to version 2.2.
Snippet of how I connect using Winsock.
#ifdef WIN32
WSADATA wsaData;
int error = WSAStartup(MAKEWORD(2,2), &wsaData);
if(error != 0) return false;
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
WSACleanup();
return false;
}
#endif
SOCKADDR_IN sin;
LPHOSTENT lpHost = gethostbyname(hostname);
bool bRet = false;
if(NULL != lpHost) {
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sin.sin_family = AF_INET;
sin.sin_port = htons(5555);
sin.sin_addr.S_un.S_addr = *(unsigned __int32*)lpHost->h_addr;
if(connect(m_socket, (SOCKADDR*)&sin,
sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
perror("connection error");
closesocket(m_socket);
} else bRet = true;
}
return bRet;
I have a problem with sending message to server socket from client.
write function returns error - bad file number. It means that I haven't permission to write to this socket.
But from another client I can write to this socket, and do it successfully.
Most interesting, that when another client connected to server my(problem) client can send message too.
the code of my client:
SOCKET OnceCommand;
struct sockaddr_in SAddress4;
struct autoC
{
char buf[4];
short fromx;
short fromy;
short tox;
short toy;
char step;
char cycle;
};
union autocomm{
char byte[14];
struct autoC command;
} Command1, Command2;
memset(&SAddress4,0,sizeof(SAddress4));
SAddress4.sin_family = AF_INET;
SAddress4.sin_port = htons(444);
SAddress4.sin_addr.s_addr = inet_addr(RobotsIP[Robot1]);
memset(&(SAddress4.sin_zero),0,8);
if((OnceCommand = socket(AF_INET,SOCK_STREAM,0))!=SOCKET_ERROR)
{
Err(OnceCommand);
if(conn = connect(OnceCommand,(struct sockaddr *)&SAddress4,sizeof(struct sockaddr))!=SOCKET_ERROR)
{
rc = write(OnceCommand,(char*)Command1.byte,sizeof(Command1.byte));
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(OnceCommand, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
Err(OnceCommand);
perror("SO_ERROR was");
}
closesocket(OnceCommand);
}
else
{
adv_printf("Client-write() is OK\n");
adv_printf("String successfully sent lol!\n");
}
shutdown(OnceCommand,2);
closesocket(OnceCommand);
}
}
in SO_ERROR was "bad file number"
I'm using sockets lib in ADAM-5510 microcontroller based with ROM-DOS.
I tried to solve this problem by using NONBLOCKing sockets, but select returns only read ready flag.
You are using 0 for the protocol. What is this supposed to be? If TCP, try using IPPROTO_TCP in the socket call, ie.
OnceCommand = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
The problem was not in client part of program. May be by the reason of using advantech socket library or another server program accepted clients' connect, but has no data to read. When i modified server program to receive data only by select it starts work fine.
all. I'm having a bit of weird problem with client server program. I have two different kinds of clients trying to connect to one server, one is just more barebone than the other with less things to do. But other wise they are practically the same. While the barebone code can connect to server and server accepts it fine, the elaborate version of it can't. The client says it's connected, sends messages (via both send() and sendto()) and gets number of bytes sent back. But the server doesn't recognize it. I'm not really sure why, esp upon comparing both versions of clients, they are really the same thing (at least until connect() is called), elaborate version has bind() whereas barebone version doesn't. Can anybody see a problem as to why these very similar codes don't work similar :P
if (argc == 3)
{
host = argv[1]; // server address
info.c_name = argv[2];
}
else
{
printf("plz read the manual, kthxbai\n");
exit(1);
}
hp = gethostbyname(host);
if (!hp)
exit(1);
printf("host found\n");
// setting up address and port structure information
bzero((char * ) &server_address, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(SERVER_PORT);
// opening up socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
exit(1);
else
printf("socket is opened: %i \n", sockfd);
info.sock_fd = sockfd;
// binding socket to a port: not in barebone version
rv = bind(sockfd, (struct sockaddr *) &server_address, sizeof(server_address));
if (rv < 0)
{
printf("MAIN: ERROR bind() %s\n", strerror(errno));
exit(1);
}
else
printf("socket is bound\n");
// connecting
rv = connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address));
printf("rv = %i\n", rv);
if (rv < 0)
{
printf("MAIN: ERROR connect() %i: %s\n", errno, strerror(errno));
exit(1);
}
else
printf("connected\n");
I'm not even sure where the problem is, whether it's the elaborate version of client or it's just the server? Thanks for any enlightenment.
If the code is really what you're using, your client is (magically!) connecting to itself, due to TCP's somewhat obscure Simultaneous connect support.
The problem here is that you aren't using the return for gethostbyname at all.
You also shouldn't bind the server port if it might be running on the local machine.