I am reading a book on sockets in c and am making a very simple server program. I copied the code verbatim. There is nothing trying to connect to this server program yet and have change the port multiple times to make sure.
The program is failing on the accept method on the first run of the loop. From what I read in the man pages, accept is supposed to block the caller until a connection is made, and not fail if there aren't connections in the queue like it is doing. Is there any reason accept would be returning a value less than 0? I will post the code up to where it fails:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//Max number of outstanding connection requests
#define MAXPEDNING 5
#define NONE
#define BUFSIZE 1024
int main(int argc, char **argv)
{
in_port_t servPort;
#ifdef CMDLINE
if(argc != 2)
{
puts("Error! Usage is <Server Port>");
return 0;
}
servPort = atoi(argv+1);
#endif //CMDLINE
#ifdef NONE
servPort = 2549;
#endif //NONE
int servSock;
if((servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
puts("socket() failed");
return 0;
}
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(servPort);
printf("Port in network order: %d\nPort in host order:%d\n", servAddr.sin_port, ntohs(servAddr.sin_port));
if((bind(servSock, (struct sockaddr*) &servAddr, sizeof(servAddr)))<0)
{
puts("bind failed");
return 0;
}
while(1)
{
struct sockaddr_in clntAddr;
socklen_t clntAddrLen = sizeof(clntAddr);
int clntSock = accept(servSock, (struct sockaddr*) &clntAddr, &clntAddrLen);
if(clntSock < 0)
{
puts("accept failed");
return 0;
}
It reaches the accept failed and quits. The only thing that is odd about my setup is that I am on a Debian VM (VirtualBox) and I am wondering if network operations are handled in a weird way. I shouldn't be even trying to accept anything because there are no connections.
You need to call listen() in between bind() and accept().
Related
Why does this header file go into a freeze state or it does not output anything even if the server is accepting connection form other scripts/tools
tcpclient.h
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#pragma once
int socket_desc;
struct sockaddr_in server_addr;
int init_client()
{
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc < 0 )
{
printf("Failed to create socket\n");
return -1;
}
return 0;
}
int connection(char *host,int port )
{
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(host);
if (connect(socket_desc, (struct sockaddr*)&server_addr, sizeof(server_addr))<0)
{
printf("Failed to connect # %s:%d\n",host,port);
return -1;
}
printf("Connected to [%s:%d]\n",host,port);
return 0;
}
using a main.c like so
int main()
{
int soc = init_client();
int con = connection("192.168.0.12",6666);
return 0;
}
the only warning I get is that the variable soc is not used
Your program works correctly in my computer.... It's not clear what do you claim on.
Anyway, after tweaking it a bit, I have some points to comment on it. I changed the ip address to 127.0.0.1 and port to 80 and started an apache server locally to check that the server is, indeed ready to accept connections.
First I checked that the connection opened locally with a telnet(1) command (you will probably have to install it in your machine as it is not installed now by default)
$ telnet localhost 80
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
^]
telnet> close
Connection closed.
$ _
then I changed several things in your code (they should not affect the run, but they will make you trouble in the future if you don't take this path)
I first created a socket.h file to put prototypes for both functions, so you don't run in trouble if you later change the prototypes.
socket.h
#ifndef _SOCKET_H
#define _SOCKET_H
int init_client(void);
int connection(const char *host, int port);
#endif /* _SOCKET_H */
As you see, I changed the parameter `host` into a `const char *` type, so the compiler knows that the string is not changed inside the function and can optimize calls, based on that.
Second, I #included the file in both modules, so if you change the interface, both modules (provider and consumer) know about the interface change.
socket.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
I used the last two includes to use strerror(errno), that gives you the reason for the connection error (mainly being a connection refused error)
#include "socket.h"
int socket_desc = -1;
struct sockaddr_in server_addr;
this is not good practice. A better solution would be to return the socket and pass it as parameter to the connection call below. Using global variables will run you into trouble later if you want to use these functions in different threads, as the socket_desc global variable is common to all the threads you will have.
int init_client(void)
{
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc < 0 )
{
printf("Failed to create socket, %s\n",
strerror(errno));
return -1;
}
return 0;
}
int connection(const char *host, int port)
{
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(host);
printf("trying connect to %s:%d\n", host, port);
if (connect(socket_desc, (struct sockaddr*) &server_addr, sizeof(server_addr))<0)
{
printf("Failed to connect # %s:%d, %s\n",
host, port, strerror(errno));
return -1;
printing here the reason of the non connection is a good idea to know what is happening.
}
printf("Connected to [%s:%d]\n",host,port);
return 0;
}
A better solution would be the following:
socket.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include "socket.h"
int init_client(void)
{
int socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc < 0 )
{
printf("Failed to create socket: %s\n",
strerror(errno));
}
return socket_desc;
}
int connection(int sd, const char *host, int port)
{
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(host);
printf("trying connect to %s:%d\n", host, port);
if (connect(sd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0) {
printf("Failed to connect # %s:%d, %s\n",
host, port, strerror(errno));
return -1;
}
printf("Connected to [%s:%d]\n", host, port);
return 0;
}
where socket.h becomes:
socket.h
#ifndef _SOCKET_H
#define _SOCKET_H
int init_client(void);
int connection(int socket_descriptor, const char *host, int port);
#endif /* _SOCKET_H */
this modifications, made that calling the program to localhost:80 resulted in:
$ a.out
trying connect to 127.0.0.1:80
Connected to [127.0.0.1:80]
$ _
while using 79 as the port resulted in:
$ a.out
trying connect to 127.0.0.1:79
Failed to connect # 127.0.0.1:79, Connection refused
Failed connection(), Connection refused
$ _
I'm trying to extend the example from here, to having to services receiving the same message from the same UDP port.
From this question, I understand that I should use SO_REUSEADDR to avoid the error of "address already in use". I have one client sending a "hello" message om port 8080 and two identical services, which simply prints out the received message from the port. SO_REUSEADDR solved the problem of using the same address, however only one of the services receives and prints out the message, while the other keep waiting.
Would it not be possible to have the same message received by both services?
The client:
// Client side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from client";
struct sockaddr_in servaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY;
int n, len;
sendto(sockfd, (const char *)hello, strlen(hello),
MSG_CONFIRM, (const struct sockaddr *) &servaddr,
sizeof(servaddr));
printf("Hello message sent.\n");
close(sockfd);
return 0;
}
One of the two identical services:
// Server side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from server";
struct sockaddr_in servaddr, cliaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
int reuse = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0)
perror("setsockopt(SO_REUSEADDR) failed");
#ifdef SO_REUSEPORT
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0)
perror("setsockopt(SO_REUSEPORT) failed");
#endif
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// Bind the socket with the server address
if ( bind(sockfd, (const struct sockaddr *)&servaddr,
sizeof(servaddr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
int len, n;
len = sizeof(cliaddr); //len is value/resuslt
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, ( struct sockaddr *) &cliaddr,
&len);
buffer[n] = '\0';
printf("Client : %s\n", buffer);
return 0;
}
I think that Sockets act like a queue to your application. Each message received from the network gets placed in that queue, and applications calling recv() or recvfrom() pop messages off of that queue.
The two clients using the same UDP port will share the same queue. I think calling recvfrom() on one client will pop a message off of the queue for that client, and make that message unavailable for the other client.
I think that generally the best approach is to have a one-to-one relationship between clients and sockets.
But, you're curious and really want the message to be available for both clients, you could experiment with passing the MSG_PEEK flag to recvfrom(). That flag changes recvfrom() to not consume the next message from the socket queue, so the other client could also receive it.
I'm trying to get into socket programming with C and my problem is that no matter what I try I cannot get my client-server model to connect over the internet except through logging into my router and port forwarding the port I'm inputting in my program. Basically my server.c blocks and waits for a connection, then it sends the time of the server to the client once it connects. I've tried to open ports on both my machines like this:
sudo iptables -A INPUT -p tcp --dport 20001 -j ACCEPT
and I downloaded the iptables-persistent package that makes sure the rules stay on a reboot. iptables -L shows me that the ports are open on both machines, but the connection still times out. I know that somehow this is possible because Steam and Discord don't have to port forward anything and they still make it happen. I have a server at home so if the solution requires a 'middle man' server to facilitate a connection between two clients, then it won't be a problem for me. Also I am on two separate networks, so that's not the problem.
The server.c:
/* --- server.c --- */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
time_t ticks;
/* creates an UN-named socket inside the kernel and returns
* an integer known as socket descriptor
* This function takes domain/family as its first argument.
* For Internet family of IPv4 addresses we use AF_INET
*/
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(20001);
/* The call to the function "bind()" assigns the details specified
* in the structure 『serv_addr' to the socket created in the step above
*/
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
/* The call to the function "listen()" with second argument as 10 specifies
* maximum number of client connections that server will queue for this listening
* socket.
*/
listen(listenfd, 10);
while(1)
{
/* In the call to accept(), the server is put to sleep and when for an incoming
* client request, the three way TCP handshake* is complete, the function accept()
* wakes up and returns the socket descriptor representing the client socket.
*/
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
/* As soon as server gets a request from client, it prepares the date and time and
* writes on the client socket through the descriptor returned by accept()
*/
ticks = time(NULL);
snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks));
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
}
and client.c:
/* --- client.c --- */
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
if(argc != 2)
{
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
memset(recvBuff, '0',sizeof(recvBuff));
/* a socket is created through call to socket() function */
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(20001);
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
/* Information like IP address of the remote host and its port is
* bundled up in a structure and a call to function connect() is made
* which tries to connect this socket with the socket (IP address and port)
* of the remote host
*/
if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
/* Once the sockets are connected, the server sends the data (date+time)
* on clients socket through clients socket descriptor and client can read it
* through normal read call on the its socket descriptor.
*/
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
{
recvBuff[n] = 0;
if(fputs(recvBuff, stdout) == EOF)
{
printf("\n Error : Fputs error\n");
}
}
if(n < 0)
{
printf("\n Read error \n");
}
return 0;
}
This line is saying what port you're connecting to on the server
serv_addr.sin_port = htons(42020);
change it to the same port number as the server and it should work just fine.
serv_addr.sin_port = htons(20001);
#include <stdio.h>
#include "http.h"
#define MAX 4096
int main()
{
char s_msg[MAX], c_msg[MAX];
printf("%d", strlen(s_msg));
// Clean buffers:
memset(s_msg,'\0',sizeof(s_msg));
memset(c_msg,'\0',sizeof(c_msg));
char *msg = "GET / HTTP/1.1\r\nUser-Agent: Hellothere\r\nHost: HOSTNAME\r\n\r\n";
int soc = init_client();
int con = connection("HOSTNAME",80);
if(send(socket_desc, msg, strlen(msg), 0) < 0){
printf("Unable to send message\n");
return -1;
}
if (recv(socket_desc, c_msg , MAX, 0)<0)
{
printf("Failed to read from server\n");
return -1;
}
printf("Recieved from server : %s\n",c_msg);
return 0;
}
Using ngrok you need to use Host header
I created a TCP client and a server in C and executed it in two terminals. But after changing and compiling the code, I could not get the output. Both server and client keep running and print nothing.
Here is my server code
/* Sample TCP server */
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
int fsize(FILE *fp){
int prev=ftell(fp);
fseek(fp, 0L, SEEK_END);
int sz=ftell(fp);
fseek(fp,prev,SEEK_SET); //go back to where we were
return sz;
}
int main(int argc, char**argv)
{
int listenfd,connfd,n, length;
struct sockaddr_in servaddr,cliaddr;
socklen_t clilen;
char* banner = "ack";
char buffer[1000];
/* one socket is dedicated to listening */
listenfd=socket(AF_INET,SOCK_STREAM,0);
/* initialize a sockaddr_in struct with our own address information for binding the socket */
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(32000);
/* binding */
bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
listen(listenfd,0);
clilen=sizeof(cliaddr);
while(1){
/* accept the client with a different socket. */
connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
// the uninitialized cliaddr variable is filled in with the
n = recvfrom(connfd,buffer,1000,0,(struct sockaddr *)&cliaddr,&clilen);//information of the client by recvfrom function
buffer[n] = 0;
sendto(connfd,banner,strlen(banner),0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
printf("Received:%s\n",buffer);
FILE *fp = fopen("serverfile.txt", "r");
length = fsize(fp);
printf("%d\n", length);
}
return 0;
}
Here is my client code
/* Sample TCP client */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char**argv)
{
int sockfd,n;
struct sockaddr_in servaddr;
char banner[] = "Hello TCP server! This is TCP client";
char buffer[1000];
if (argc != 2)
{
printf("usage: ./%s <IP address>\n",argv[0]);
return -1;
}
/* socket to connect */s
sockfd=socket(AF_INET,SOCK_STREAM,0);
/* IP address information of the server to connect to */
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=inet_addr(argv[1]);
servaddr.sin_port=htons(32000);
connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
sendto(sockfd,banner,strlen(banner),0, (struct sockaddr*)&servaddr,sizeof(servaddr));
n=recvfrom(sockfd,buffer,10000,0,NULL,NULL);
buffer[n]=0;
printf("Received:%s\n",buffer);
return 0;
}
Your main problem is that you are not checking the results of any of your operations on the sockets, so it is entirely possible that the server or client is reporting an error message that makes the answer to your problem obvious.
In particular, if the server fails to bind or listen to the listen socket, it will just go into an infinite loop making failed accepts, reads and writes forever.
I suspect that, what happens is that when you restart the server, the previous socket is still in the TIME_WAIT state, so it can't bind to the port. You can get around this by using the following after creating the socket:
int reuseaddr = 1;
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&reuseaddr,sizeof(reuseaddr))==-1)
{
fprintf(stderr, "%s",strerror(errno));
exit(1);
}
Note how the above checks the return result and reports an error on failure. You need to do this or similar after every call to socket(), listen(), bind(), connect(), recvfrom(), sendto() and close().
Note, how I put close() in that list. You really must call it on the connect socket when you are finished with it, especially on the server or you will leak the file descriptor in connfd.
I've successfully made an "echo client", and I'd like to add robustness before moving along to the rest of my project. Notably I'd like to view the "TCP window size" value inside the TCP header, and ensure that I don't flood the server with my next transmission.
I am not sure if this is possible without using raw sockets and forming/parsing the TCP header myself. While that isn't impossible, I'd prefer to use built in functions to access the header with my current code if possible. Please let me know if you have any suggestions.
#include "../include/a8gcc.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#define buffer_len 512
/* server address */
#define SERVER "192.168.2.115"
/* server port number */
#define SERVPORT 10001
int main(void)
{
struct sockaddr_in serv_addr;
struct hostent *server;
int sock_fd, num_read = 0;
char in_data[buffer_len];
printf("is_ethernet from GCC");
setbuf(stdout, NULL);
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if(sock_fd < 0){
perror("Opening socket error");
exit(1);
}else{
printf("Opening the socket...OK.\n");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
server = gethostbyname(SERVER);
if(server == NULL){
printf("%s \n", h_errno);
perror("getting host address error");
exit(1);
}
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(SERVPORT);
if (connect(sock_fd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){
perror("ERROR connecting");
exit(1);
}
while(1){
num_read = read(sock_fd,in_data,buffer_len);
write(sock_fd,in_data,num_read);
}
return 0;
}
I do not believe that it is possible for you to examine the actual content of the TCP/IP headers from within your code unless you are going to use raw sockets and generate the packets yourself. :( Sorry!