Creating a new tcp socket - server side - c

I'm writing a simple server code.
After running the code,I'm trying to connect the server using "telnet localhost 8000" and I get the next error: "Connection closed by foreign host" and the server closes.
this is the code I wrote:
void main(int argv,void * argc)
{
//int socket(int af, int type, int protocol);
int listen_sckt;
int new_socket;
int addrlen;
struct sockaddr_in addr;
/*
#include <netinet/in.h>
struct sockaddr_in {
short sin_family; // e.g. AF_INET
unsigned short sin_port; // e.g. htons(3490)
struct in_addr sin_addr; // see struct in_addr, below
char sin_zero[8]; // zero this if you want to
};
struct in_addr {
unsigned long s_addr; // load with inet_aton()
};
*/
listen_sckt = socket(AF_INET,SOCK_STREAM,0);
if(listen_sckt == -1){
perror("SOCKET ERR\n");
return;
}
printf("Socket succesfulyl opened\n");
{
/*
binding a docket
syntax:
int bind(int s, struct sockaddr *addr, int addrlen);
connect the socket to a logic port.
so the other side will know where to "find" the other side
*/
}
addr.sin_family = AF_INET;x`
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(8000);
//binding command
if(-1 == bind(listen_sckt,(struct sockaddr*)&addr,sizeof(addr))){
perror("BINDING ERR\n");
}
printf("Binding succesfully done\n");
/* Listen()
Before any connections can be accepted, the socket must be told to listen
for connections and also the maximum number of pending connections using listen()
Includes:
#include <sys/socket.h>
Syntax:
int listen(int socket, int backlog);
socket - the socket file descriptor
backlog - the max number of pedding the socket will hold
C source:
*/
listen(listen_sckt,2);
/*
To actually tell the server to accept a connection, you have to use the function accept()
Includes:
#include <sys/socket.h>
Syntax:
int accept(int s, struct sockaddr *addr, int *addrlen);
*/
addrlen = sizeof(struct sockaddr_in);
new_socket = accept(listen_sckt,(struct sockaddr*)&addr,&addrlen);
if(new_socket<0){
perror("Accept ERR\n");
}
printf("Acept success\n");
}
Thanks.

That's because once you have accepted the connection, you exit the program which causes all descriptors (including sockets) to be closed.
If you want to do something with the socket, you should do that after the accept call. Like having a read/write loop.
And you should probably have a loop around the whole thing, so your program can accept new connections once the previous is closed.

Related

UDP socket demultiplexing at server port

TCP socket demultiplexing at the server port (which listens for multiple TCP connections) happens with a separate socket descriptor created for each established TCP connection(though the accept() call) and the socket descriptor is tightly coupled with tuple [source IP address, source port, destination IP address, destination IP address]. Over this established connection we can use the high layer application protocols like HTTP, FTP, SSH etc.,
But in case of UDP there is no session/connection established between the peers. The server waiting at the particular port receives the message from any client. The client's IP address and port number is known after receiving the message(populated in the socket address structure). From the address structure the messages can be demultiplexed and given to respective applications.
Over the server port, If I want to establish a connected session over UDP[like the tuple mentioned in case of TCP] so that communication between the server and client (between particular port on server and client) can be demultiplexed before receiving the message(without inferring the same from socket address structure) so that the higher layer protocols can work like on TCP (ofcourse higher layer protocols like DTLS taking care of the reliability)
Below is the code for UDP server(leveraging the connect() API to keep the UDP socket connected) and UDP client
// server program for udp connection
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PORT 5000
#define MAXLINE 1000
//logical thread num
static unsigned int threadnum = 0;
struct pass_info {
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
unsigned int threadnum;
};
char *message = "Hello Client";
void* connection_handle(void *info) {
int fd = 0;
char buffer[100];
int n = 0;
const int on = 1;
struct pass_info *pinfo = (struct pass_info*) info;
printf("Executing thread : %d\n", pinfo->threadnum);
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
printf("Error socket!!!");
return;
}
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on));
bind(fd, (const struct sockaddr *) &pinfo->server_addr, sizeof(struct sockaddr_in));
connect(fd, (struct sockaddr *) &pinfo->client_addr, sizeof(struct sockaddr_in));
while(1)
{
n = recv(fd, buffer, sizeof(buffer), 0);
if (n < 0)
{
printf("receive failed! in thread : %d", pinfo->threadnum);
break;
}
buffer[n] = '\0';
printf("Thread num %d: Recv message - %s\n", pinfo->threadnum, buffer);
n = send(fd, message, sizeof(message), 0);
if (n < 0)
{
printf("send failed! in thread : %d", pinfo->threadnum);
break;
}
}
free(info);
return NULL;
}
int main()
{
char buffer[100];
int listenfd, len, sockfd;
const int on = 1;
struct sockaddr_in servaddr, cliaddr;
bzero(&servaddr, sizeof(servaddr));
struct pass_info *info;
pthread_t tid;
// Create a UDP Socket
listenfd = socket(AF_INET, SOCK_DGRAM, 0);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
servaddr.sin_family = AF_INET;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on));
// bind server address to socket descriptor
bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
while (1)
{
//receive the datagram
len = sizeof(cliaddr);
int n = recvfrom(listenfd, buffer, sizeof(buffer),
0, (struct sockaddr*)&cliaddr,&len); //receive message from server
buffer[n] = '\0';
printf("Main thread: Recv message - %s\n", buffer);
n = sendto(listenfd, message, MAXLINE, 0, (struct sockaddr*)&cliaddr, sizeof(cliaddr));
info = (struct pass_info*) malloc (sizeof(struct pass_info));
memcpy(&info->server_addr, &servaddr, sizeof(struct sockaddr_in));
memcpy(&info->client_addr, &cliaddr, sizeof(struct sockaddr_in));
threadnum++;
info->threadnum = threadnum;
if (pthread_create(&tid, NULL, connection_handle, info) != 0) {
perror("pthread_create");
exit(-1);
}
}
}
// udp client program
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<stdlib.h>
#define PORT 5000
#define MAXLINE 1000
int main()
{
char buffer[100];
char *message = "Hello Server";
int sockfd, n;
struct sockaddr_in servaddr, cliaddr;
int len = 0;
// clear servaddr
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(PORT);
servaddr.sin_family = AF_INET;
// create datagram socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
while(1)
{
sleep(3);
sendto(sockfd, message, MAXLINE, 0, (struct sockaddr*)&servaddr, sizeof(servaddr));
// waiting for response
recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&cliaddr, &len);
puts(buffer);
}
}
Queries:
Whether this would be the right way to do de-multiplexing at the UDP socket level
The server listens for any UDP packets from the client. once it receives a message, new socket descriptor is created and the connect() API is called so that the client's IP address, port is registered with this newly created socket descriptor and from here on newly created socket descriptor will used to send and receive messages to the particular client's IP address and port. Whether it is a fool proof method
Are there any other well known methods to use the higher layer protocols(protocols supporting reliability like DTLS) over UDP

Recv() not working in separate thread, C socket programming

I am having some issues with the recv() function returning a -1 in a C program with threading. The basis of the program is to receive a few request packets in one thread and having a second thread send out a multicast to all registered clients.
Below is the code for my server:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
#include <pthread.h>
#define SERVER_PORT 5654
#define MAX_LINE 256
#define MAX_PENDING 5
/*structure of the packet*/
struct packet{
short type;
char data[MAX_LINE];
};
struct data_packet{
short header;
char data[MAX_LINE];
};
/* structure of Registration Table */
struct registrationTable{
int port;
char name[MAX_LINE];
int req_no;
};
struct global_table{
int sockid;
int reqno;
};
void *join_handler(struct global_table *rec){
int new_s;
struct packet packet_reg;
new_s = rec->sockid;
printf("In thread: %i\n",new_s);
printf("In thread: %i\n",rec->reqno);
if(recv(new_s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\ncouldnt receive first reg packet\n");
exit(1);
}
pthread_exit(NULL);
}
int main(int argc, char* argv[])
{
/* initilizing all of the packets*/
struct packet packet_reg;
struct registrationTable table[10];
struct global_table record[20];
struct sockaddr_in sin;
struct sockaddr_in clientAddr;
char buf[MAX_LINE];
int s, new_s;
int len;
int i;
struct hostent *he;
struct in_addr **addr_list;
pthread_t threads[2];
/* setup passive open */
if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("tcpserver: socket");
exit(1);
}
/* build address data structure */
bzero((char*)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
if(bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0){
perror("tcpclient: bind");
exit(1);
}
listen(s, MAX_PENDING);
/* wait for connection, then receive and print text */
while(1){
if((new_s = accept(s, (struct sockaddr *)&clientAddr, &len)) < 0){
perror("tcpserver: accept");
exit(1);
}
/* print the port of the client*/
printf("\n Client's port is %d \n", ntohs(clientAddr.sin_port));
/* receive the first registration packet*/
if(recv(new_s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\ncouldnt receive first reg packet\n");
exit(1);
}
struct global_table client_info;
client_info.sockid = ntohs(clientAddr.sin_port);
client_info.reqno = 1;
pthread_create(&threads[0],NULL,join_handler, &client_info);
}
}
Client:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#define SERVER_PORT 5654
#define MAX_LINE 256
/*structure of the packet*/
struct packet{
short type;
char data[MAX_LINE];
};
struct data_packet{
short header;
char data[MAX_LINE];
};
int main(int argc, char* argv[])
{
struct packet packet_reg;
struct hostent *hp;
struct sockaddr_in sin;
char *host;
char buf[MAX_LINE];
int s;
int len;
char hostname[1024];
hostname[1023] = '\0';
if(argc == 2){
host = argv[1];
}
else{
fprintf(stderr, "usage:newclient server\n");
exit(1);
}
/* translate host name into peer's IP address */
hp = gethostbyname(host);
if(!hp){
fprintf(stderr, "unkown host: %s\n", host);
exit(1);
}
/* active open */
if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("tcpclient: socket");
exit(1);
}
/* build address data structure */
bzero((char*)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
if(connect(s,(struct sockaddr *)&sin, sizeof(sin)) < 0){
perror("tcpclient: connect");
close(s);
exit(1);
}
/* main loop: get and send lines of text
all you have to do to start the program is
enter any key */
while(fgets(buf, sizeof(buf), stdin)){
/* Find the hostname and print it*/
gethostname(hostname, 1023);
printf("Hostname: %s\n", hostname);
/* populate the info for the first registration packet*/
packet_reg.type = htons(121);
strcpy(packet_reg.data,hostname);
/*send the registration packet to the server*/
if(send(s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\nsend failed\n");
exit(1);
}
/* Print the contents of the first registration packet*/
printf("Sent 1st reg packet data: %s\n",packet_reg.data );
printf("Sent 1st reg packet type: %i\n",ntohs(packet_reg.type));
/* create the second registration packet.
I created separate packets for this so
it was clearer*/
packet_reg.type = htons(121);
strcpy(packet_reg.data,hostname);
/*send the second registration packet to the server*/
if(send(s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\nsend failed\n");
exit(1);
}
/* Print the contents of the second registration packet*/
printf("Sent 2nd reg packet data: %s\n",packet_reg.data );
printf("Sent 2nd reg packet type: %i\n",ntohs(packet_reg.type));
}
}
So Basically, I am creating the connection and wait to receive the first registration packet (packet_reg). This works and I receive the packet. I then send control of the program to the thread. However, while the "rec" variable correctly passes the information, the subsequent receive does not work and exits with a value less than 0.
Other information: The packets are all sent and received correctly, but the client's port, printed from
printf("\n Client's port is %d \n", ntohs(clientAddr.sin_port));
is listed as 0. I am not sure if this is a problem, but the code works fine when all of the receives are in the main function.
Another issue could be that I get the following warning:
passing argument 3 pf pthread_create from incompatible pointer type expected 'void * (*) (void *)' but argument of type 'void * (*) (struct global_table*)'
I have researched this warning and know that it has to do with receiving the data as void and then casting. However, the data is being sent to the thread properly when I print from there to check.
Basically, the problem is that while I can receive the packets from the client outside the thread, with the same statements, when I am inside the thread the packets are not received and recv() returns -1.
I accidentally set the receive to the port and not the socket. I am a dummy. I know that a lot of you were telling me how bad the code is constructed regarding TCP conventions. I am building off of code for an assignment, nothing I can do about the professor telling us that this is the way to do it.

C: listen() API returning -1

I'm using below code to create a server program in c. The code is taken from here
#include <Winsock.h>
#include <string.h>
#include <ws2tcpip.h>
#include<conio.h>
int main(){
int welcomeSocket, newSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(7891);
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Bind the address struct to the socket ----*/
bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
/*---- Listen on the socket, with 5 max connection requests queued ----*/
if(listen(welcomeSocket,5)==0)
printf("Listening\n");
else
printf("Error %d\n",listen(welcomeSocket,5));
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
/*---- Send message to the socket of the incoming connection ----*/
strcpy(buffer,"Hello World\n");
send(newSocket,buffer,13,0);
getch();
return 0;
}
I've changed the code little bit to make it work in dev-c but in the output it's printing error i.e it's executing the else condition. Anyone have any idea why? And how to debug this?
I've tried changing the port no. It didn't work.
On Windows, you have to initialize the networking subsystem first by calling WSAStartup, before you can make any calls to socket/network-related functions.
WSADATA wsaData;
int wsaRc = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (wsaRc != 0) {
fprintf(stderr, "WSAStartup failed with error: %d\n", wsaRc);
return 1;
}
/* Socket related functions callable from here on */
The example-code you've linked was written for UNIX systems, which do not have that API-requirement.
Please note, that you also
[...] must call the WSACleanup function for every successful
time the WSAStartup function is called.
(From the WSAStartup documentation).

TCP Client and Servers in C

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.

accept() keeps returning 0

This is a simple server that merely accepts connections, then prints the socket descriptor. For some reason, whenever I run this the only socket descriptors I receive are of value 0. This even occurs with multiple clients connecting simultaneously. I seem to be misunderstanding something to do with the behavior of accept(), or there is some bug I cannot locate in my code. Here is the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
/* Utility for consisely killing the program. */
void abort_program(const char *error_message)
{
fputs(error_message, stderr);
exit(EXIT_FAILURE);
}
/* Establishes a passive listening port, returns socket descriptor. */
int setup_passive_port(int port)
{
struct protoent *ptrp; // pointer to a protocol table entry
struct sockaddr_in sad; // structure to hold server's address
int sd; // socket descriptor for listening
/* Map TCP transport protocol name to protocol number. */
if (((long int) (ptrp = getprotobyname("tcp"))) == 0)
abort_program("ERROR: Cannot map TCP to protocol number\n");
/* Create a socket. */
sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if (sd < 0)
abort_program("ERROR: Socket creation failed\n");
/* Prepare the socket address structure. */
memset((char *) &sad, 0, sizeof(sad));
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = INADDR_ANY;
sad.sin_port = htons((u_short) port);
/* Bind a local address to the socket. */
if (bind(sd, (struct sockaddr*) &sad, sizeof(sad)) < 0)
abort_program("ERROR: Bind failed\n");
/* Establish passive listener socket. */
if (listen(sd, 0) < 0)
abort_program("ERROR: Listen failed\n");
return sd;
}
int main(int argc, char *argv[])
{
struct sockaddr_in cad; // structure to hold client's address
int alen; // length of address
int sd; // incoming socket
int listener; // listening socket
listener = setup_passive_port(30000);
while (1) {
if (sd = accept(listener, (struct sockaddr*) &cad, &alen) < 0)
abort_program("ERROR: Accept failed\n");
printf("%d\n", sd);
}
}
Can you help me understand why? Thanks for your consideration.
One thing you need to do is to set your alen to the sizeof(sockaddr_in) prior to calling accept(). The other is that at least clang complains about the missing brackets within your if( accept()...) line. Here the fixed up version.
telnet localhost 30000 worked as expected.
Also changed your int alen to socklen_t alen while being at it.
int main(int argc, char *argv[])
{
struct sockaddr_in cad; // structure to hold client's address
socklen_t alen = sizeof(sockaddr_in); // length of address
int sd; // incoming socket
int listener; // listening socket
listener = setup_passive_port(30000);
while (1) {
if ((sd = accept(listener, (struct sockaddr*) &cad, &alen)) < 0)
abort_program("ERROR: Accept failed\n");
printf("%d\n", sd);
}
}

Resources