I'm working on a C program that creates a connection between a client and server. When I run connect on the socket I've already created I keep getting an error that I'm passing an invalid argument.
Any help would be awesome!
void client(char* ipAddress, char* serverPort){
//code for setting up the IP address and socket information from Beej's Guide to Network Programming
//Need to setup two addrinfo structs. One for the client and one for the server that the connection will be going to
int status;
//client addrinfo
struct addrinfo hints, *res; // will point to the results
//server addrinfo
int socketDescriptor;
int addressLength;
memset(&hints, 0, sizeof hints); // make sure the struct is empty
hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
//setup client socket
if ((status = getaddrinfo(ipAddress, serverPort, &hints, &res)) != 0) {
printf("%s \n", "This error above");
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
if((socketDescriptor = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) ==-1){
perror("client: socket");
}
addressLength = sizeof hints;
if(connect(socketDescriptor, res->ai_addr, addressLength)==-1){
close(socketDescriptor);
perror("client: connect");
}
}
Apart from some inconsistent variable names in your code,
this seems to be wrong:
addressLength = sizeof hints;
if(connect(socketDescriptor, res->ai_addr, addressLength)==-1) ...
It should be
if(connect(socketDescriptor, res->ai_addr, res->ai_addrlen)==-1) ...
Related
I've got a small program with a client and server. The server starts, connects to the client and receives a host and second port number from the client, then sends some information back to the client about it's directory. The function in the server that sends data back works something like this:
void sendStuff(char *host, char *port) {
int sockfd, numbytes;
struct addrinfo hints, *servinfo;
struct sockaddr_storage client_info;
socklen_t addr_size;
size_t i = 0;
int rv;
// clear hints
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
memset(&servinfo, 0, sizeof(servinfo));
if ((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
}
// create socket
sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
if (sockfd == -1) {
perror("There was an error creating your socket.");
close(sockfd);
exit(1);
}
// connect using socket
int conn;
conn = connect(sockfd, servinfo->ai_addr, servinfo->ai_addrlen);
if(conn == -1) {
perror("Error connecting to server.");
close(sockfd);
exit(1);
}
send(sockfd, "hey!", strlen("hey!"), 0);
}
Currently testing over localhost, which is being printed as 16.2.197.67 on the client. That doesn't seem like a localhost IP, so I suppose I could be screwing up the host somehow. Connecting to the waiting socket over telnet works, but not through this function.
I need to program a distributed hash table with P2P. The peer which gets the request from the client needs to have an open connection to send the response back and also needs to open a connection to its predecessor to receive the information. I tried using accept a second time on the same socket but it didn't work.
I read a few solutions about forking but I'm not sure if it's suitable for my needs. (And I'm not really sure how to implement it correctly here)
My basic setup:
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if ((gai_status = getaddrinfo(NULL, port, &hints, &md_srvinfo)) != 0) {
fprintf(stderr, "error: %s\n", gai_strerror(gai_status));
exit(gai_status);
}
int md_listen_socket = socket(md_srvinfo->ai_family, md_srvinfo->ai_socktype, md_srvinfo->ai_protocol);
int yes;
setsockopt(md_listen_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(1));
bind(md_listen_socket, md_srvinfo->ai_addr, md_srvinfo->ai_addrlen);
listen(md_listen_socket, 2);
while(1) {
// accept connection
struct sockaddr_storage client_address;
socklen_t addr_size = sizeof(client_address);
int md_active_socket;
md_active_socket = accept(md_listen_socket, (struct sockaddr *) &client_address, &addr_size);
.
.
.
.
recv(stuff from predecessor peer)
send(stuff to md_active_socket)
}
Edit:
struct addrinfo *pred_srvinfo;
getaddrinfo(NULL, pred_port, &hints, &pred_srvinfo);
int pred_listen_socket = socket(pred_srvinfo->ai_family, pred_srvinfo->ai_socktype, pred_srvinfo->ai_protocol);
struct sockaddr_storage pred_address;
socklen_t pred_addr_size = sizeof(pred_address);
int pred_active_socket = accept(pred_listen_socket, (struct sockaddr *) &pred_address, &pred_addr_size);
connect(pred_active_socket, pred_srvinfo->ai_addr, pred_srvinfo->ai_addrlen);
Can someone lead me to the right path?
I'm trying to create a server client so I can have a better understanding of how they work, however I'm having an issue, whenever I make the listen() call windows gives me an error with the code 10045, I looked it up and it seems to be because the operation is not supported, however I'm confused as to why this is happening because from what I understand the listen() call should work on tcp sockets. Here's the source code for how I'm initializing the socket
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
int sockfd, n;
struct addrinfo hints, *servinfo;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_protocol = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if((n = getaddrinfo(NULL, argv[1], &hints, &servinfo)) != 0){
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(n));
return EXIT_FAILURE;
}
if((sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) < 0){
fprintf(stderr, "%d\n", WSAGetLastError());
perror("socket");
return EXIT_FAILURE;
}
if((n = bind(sockfd, servinfo->ai_addr, servinfo->ai_addrlen)) == -1){
fprintf(stderr, "%d\n", WSAGetLastError());
perror("bind");
return EXIT_FAILURE;
}
if(listen(sockfd, 1) == -1){ //error
fprintf(stderr, "%d\n", WSAGetLastError());
perror("listen");
return EXIT_FAILURE;
}
You set the wrong protocol/socket type:
hints.ai_protocol = SOCK_STREAM;
If you read the addrinfo structure reference the socket type should be in the ai_socktype field:
hints.ai_socktype = SOCK_STREAM;
Since you set the wrong ai_protocol the socket call will create the wrong type of socket for you, and the listen call will fail.
The lesson here is to always read the documentation.
Basically my server/client socket functions work perfectly fine using the loopback address, or even my eth0 address on my laptop. Howver, once I move my code into the test environment it will be used in, I get connection time outs, or connection refused depending on the changes I have tried to make.
As of now the code I am about to post results in a Connection time out.
CLIENT
void buildConnection(int* txmt_sock, Connection conn_info)
{
struct sockaddr_in servinfo; /* server address */
servinfo.sin_family = AF_INET;
servinfo.sin_addr.s_addr = INADDR_ANY;
servinfo.sin_port = htons(conn_info.port);
if(inet_aton(conn_info.ip, &servinfo.sin_addr) < 1)
{
fprintf(stderr, "Read error: %s\n", strerror(errno));
abort();
}
/*int socket(int domain, int type, int protocol)*/
if ((*txmt_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("client: socket");
abort();
}
/*int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);*/
if (connect(*txmt_sock,(struct sockaddr *)&servinfo,(socklen_t)sizeof(servinfo)) == -1)
{
close(*txmt_sock);
perror("client: connect");
abort();
}
printf("Successfully connected on port %s:%d\n", conn_info.ip, conn_info.port);
}
SERVER
void returnConnection(Connection* conn_info)
{
int status, ext_conn, yes = 1;
char portStr[5];
struct addrinfo hints, *servinfo;
struct sockaddr_storage ext_addr;
socklen_t addr_size;
struct sockaddr *restrict;
/* Formats PORT for use with getaddrinfo(), can't cast #define*/
snprintf(portStr, 6, "%d", conn_info->port);
memset(&hints, 0, sizeof(hints)); /*make sure the struct is empty*/
hints.ai_family = AF_UNSPEC; /*don't care IPv4 or IPv6*/
hints.ai_socktype = SOCK_STREAM; /*TCP stream sockets*/
hints.ai_flags = AI_PASSIVE; /*fill in my IP for me*/
if ((status = getaddrinfo(NULL, portStr, &hints, &servinfo)) != 0)
{
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
if((conn_info->listen_sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1)
{
fprintf(stderr, "Socket error: %s\n", strerror(errno));
exit(1);
}
if(setsockopt(conn_info->listen_sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1)
{
perror("setsockopt");
exit(1);
}
if(bind(conn_info->listen_sock, servinfo->ai_addr, servinfo->ai_addrlen) == -1)
{
fprintf(stderr, "Bind error: %s\n", strerror(errno));
exit(1);
}
freeaddrinfo(servinfo);
if(listen(conn_info->listen_sock, 1) == 1)
{
fprintf(stderr, "Listening error: %s\n", strerror(errno));
exit(1);
}
addr_size = sizeof(ext_conn);
if((ext_conn = accept(conn_info->listen_sock, (struct sockaddr *)&ext_addr, &addr_size)) == -1)
{
fprintf(stderr, "Accept error: %s\n", strerror(errno));
exit(1);
};
conn_info->receiving_sock = ext_conn;
}
This is a multi-threaded program that collects image data from 8 different ports/threads. I use my Connection struct to store all the pertinent data for each thread. Each thread has it's own Connection.
typedef struct connection{
char* file;
int port;
char* ip;
pthread_t *thread;
}Connection;
Connection->ip is not used in the server side, but is uses on the Client side. The server side of the code resides on a multi-cpu, multi-nic IBM server. I am not certain if I need to manually assign the IP or not because of that. I am assuming the OS and network cards manage on their own using the incoming PORT numbers from the clients, and the individual PORT numbers that my Server threads listen on. But all I know is that it works on my laptop to itself.
It's a completely new vanilla install on this machine with openSuse, so I don't think any of the ports I am using, 5050-5053 and 5055-5058, are turned off or anything like that.
I am writing a small socket program in C. In server side I create a socket descriptor using socket() system call, then I am binding that socket with a port. After this I am trying to get the IP/Port no of the descriptor, it gives port no different then the bind port no. I am trying to get back IP/Port using getsockname() method, Is it right to use this method ? Please help me.
#define SERVER_ADDR "127.0.0.1"
#define SERVER_PORT "9090" // actual port no I am binding
#define QUEUE_LENGTH 10
int main()
{
struct addrinfo hints, *servinfo, *temp;
memset(&hints,0,sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
// here I am passing SERVER_PORT == 9090
int status = getaddrinfo(SERVER_ADDR,SERVER_PORT,&hints,&servinfo);
if(status != 0)
{
printf("Server: getaddrinfo() errored with code %d\n",status);
return;
}
int sfd = -1;
for(temp = servinfo; temp != NULL; temp = servinfo->ai_next)
{
sfd = socket(temp->ai_family,temp->ai_socktype,temp->ai_protocol);
if(sfd == -1)
{
printf("Server: Socket error with code %d\n",sfd);
continue;
}
status = bind(sfd,temp->ai_addr,temp->ai_addrlen);
if(status == -1)
{
printf("Server: Bind error with code %d\n",status);
continue;
}
printf("Server: Bind Successful\n");
// un necessary code goes here
struct sockaddr_in server_address;
char ipv4[INET_ADDRSTRLEN];
int addr_size = sizeof(server_address);
// i am using below method to get the port no from socket descriptor
getsockname(sfd, (struct sockaddr *)&server_address, &addr_size);
// I am expecting below will print 9090. but it prints different port no why ?
printf("Server Port: %d\n",server_address.sin_port);
printf("Port from getsddrinfo: %d\n",( (struct sockaddr_in *)temp->ai_addr)->sin_port);
inet_ntop(AF_INET, &(server_address.sin_addr),ipv4,INET_ADDRSTRLEN);
printf("Server IP Address: %s\n",ipv4);
// un necessary code ends here
break;
}
if(temp == NULL)
{
printf("Server: Failed to bind\n");
return;
}
status = listen(sfd,QUEUE_LENGTH);
if(status == -1)
{
printf("Server: Listening failed\n");
return;
}
printf("Server: waiting for coneections...\n");
while(1)
{
printf("Server: Main loop, will wait for client to connect...\n");
struct sockaddr client_address;
int addr_length = sizeof client_address;
// accepting client
int new_sfd = accept(sfd,&client_address,&addr_length);
}
printf("Server: Done!\n");
}
Output is:
Server: Bind Successful
Server Port: 33315 --> why this different from one I have binded (9090)
Port from getsddrinfo: 33315 --> why this different from one I have binded (9090)
Server IP Address: 127.0.0.1
Server: waiting for coneections...
Server: Main loop, will wait for client to connect...
The decimal members of struct sockaddr are returned in network byte order.
So you need to convert such values to host byte order, using the ntoh family of functions before using them, printing them.
add hints.sin_port = htons( 9090 );after hints.ai_socktype = SOCK_STREAM;