How to setup DGRAM socket in C - c

My server connects successfully, but I am not seeing any message from client/server in my terminal whenever I use SOCK_DGRAM. Am I missing any functions for this type of socket? The code below works fine with SOCK_STREAM with this I also have one small problem, I am not seeing message from client in my server terminal but I do see "Connected to server" in client terminal. Can someone advise?
Client
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
int main() {
int socket_server;
int socket_connect;
int socket_listen;
char buffer[256];
char sendMsg[256] = "Received from client";
struct sockaddr_in socket_address;
socket_address.sin_family = AF_INET;
socket_address.sin_port = htons(4003);
socket_address.sin_addr.s_addr = INADDR_ANY;
socket_server = socket(AF_INET, SOCK_DGRAM, 0);
socket_connect= connect(socket_server, (struct sockaddr*) &socket_address, sizeof(socket_address));
socket_listen = listen(socket_server, 5);
recv(socket_server, &buffer, sizeof(buffer), 0);
send(socket_server, &sendMsg, sizeof(sendMsg), 0);
printf("%s", buffer);
return 0;
}
Server
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
int main() {
int socket_server;
int socket_bind;
int socket_listen;
char buffer[256] = "Connected to server";
char fromClient[256];
struct sockaddr_in socket_address;
socket_address.sin_family = AF_INET;
socket_address.sin_port = htons(4003);
socket_address.sin_addr.s_addr = INADDR_ANY;
socket_server = socket(AF_INET, SOCK_DGRAM, 0);
socket_bind = bind(socket_server, (struct sockaddr*) &socket_address, sizeof(socket_address));
socket_listen = listen(socket_server, 5);
for(;;) {
int socket_accept = accept(socket_server, NULL, NULL);
send(socket_accept, &buffer, sizeof(buffer), 0);
recv(socket_accept, &fromClient, sizeof(fromClient), 0);
printf("%s", fromClient);
}
return 0;
}

UDP sockets don't use listen or accept.
Messages from all clients are received on the original socket to which you bound the address. The connect is not really establishing a connection, it is just saving the remote address so that it knows where to send each datagram when using send (as opposed to sendto).
It also looks odd that the client expects the first message to come from the server, probably because you expected the server to detect the connect, which it does not. Normally the server would be up and running and send responses to requests, so the client needs to send a request and then wait for a response, and the server needs to wait for a request and then send a response. The server will need to use recvfrom so that it knows where to send the response!

Related

What's wrong with this code that attempts to listen repeatedly on a socket?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <pthread.h>
#include <arpa/inet.h>
struct sockaddr_in server, acc;
int sock;
int stuff(void) {
char buffer[2000];
recv(sock, buffer, sizeof(buffer), 0);
send(sock, "HTTP/1.1 200 OK\nContent-Type: text/html\n\nHello", sizeof("HTTP/1.1 200 OK\nContent-Type: text/html\n\nHello"), 0);
shutdown(sock, SHUT_RDWR);
return 0;
}
int main(void) {
int size;
sock = socket(AF_INET, SOCK_STREAM, 0);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(1111);
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1) {
perror("Error:");
return 1;
}
while (1) {
listen(sock, 5);
sock = accept(sock, (struct sockaddr*)&acc, &size);
printf("accepted\n");
stuff();
close(sock);
}
}
This is meant to be an extremely basic HTTP server.
I don't know what's going wrong, but the connection seems to not end with the client.
Opening this in the browser, it doesn't stop loading and the console is flooded with "accepted" (line 42). No new connections can be accepted.
After your program accepts a connection, it forgets about the socket that listens for new connections, does remember the newly connected socket, does some stuff with that socket, closes it, then tries to accept another connection from the connected socket that it just closed.
There are two problems here:
It's the wrong socket
Even if it was the right socket, it's closed
You create socket number 3 (for example) to wait for new connections. You wait for a connection on socket 3 and the new connection is socket number 4 (for example). Then you do the stuff, then you close socket 4, then you wait for a new connection on socket 4. Do you see the mistake here? Socket 3 is the one that accepts connections.
Since you are not new to programming, you should be able to figure out how to make your program call accept with the right socket.

"Connected" UDP sockets, communication in both directions?

How do I achieve 2 way communication on a connected UDP sockets ?
I can send message from client to server, but can not get a message from server. Here is my code. I think that problem must be in the server side, but I don't know how to solve that problem. I have intentionally removed error checking just to post on SO & keep my post short. I am not receiving any errors on any side.
I can get this program running with not connected UDP sockets, but can't with connected socket.
Server.c
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
int main()
{
int sockfd;
struct sockaddr_in me;
char buffer[1024];
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&me, '\0', sizeof(me));
me.sin_family = AF_INET;
me.sin_port = htons(8080);
me.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(sockfd, (struct sockaddr *)&me, sizeof(me));
recv(sockfd, buffer, 1024, 0);
printf("[+]Data Received: %s\n", buffer);
strcpy(buffer, "Hello Client\n");
send(sockfd, buffer, 1024, 0);
printf("[+]Data Send: %s\n", buffer);
return 0;
}
Client.c
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
int main()
{
int sockfd;
struct sockaddr_in other;
char buffer[1024];
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&other, '\0', sizeof(other));
other.sin_family = AF_INET;
other.sin_port = htons(8080);
other.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sockfd, (struct sockaddr *)&other, sizeof(other));
strcpy(buffer, "Hello Server\n");
send(sockfd, buffer, 1024, 0);
printf("[+]Data Send: %s\n", buffer);
recv(sockfd, buffer, 1024, 0);
printf("[+]Data Received: %s\n", buffer);
return 0;
}
Output of Server
[+]Data Received: Hello Server
[+]Data Send: Hello Client
Output of Client
[+]Data Send: Hello Server
// Here it does not receive the message sent by server.
On linux, straceing the executable, the server send does say this:
sendto(3, "Hello Client\n\0\0\0\310$\220\4J\177\0\0\0\0\0\0\0\0\0\0"...,
1024, 0, NULL, 0) = -1 EDESTADDRREQ (Destination address required)
i.e. the server socket indeed does not know the address it needs to send to. Any UDP socket must make the other end of the socket known by either connecting, or providing the destination socket address in sendto.
connect on an UDP socket means just setting a default address for send.
To connect the socket on the "server" side, with an unknown party you should use recvfrom to find out the socket address of the sending party - then you can connect using this address or continue using sendto. With sendto the same socket can communicate with many different parties concurrently.
The TCP server/client sockets are a different case, because listen/accept on the server side returns a new connected socket that is distinct from the original server socket.

C programming TCP server and client connection errors

I want to make a TCP connection between my Virtual private server and my host machine using a TCP socket connection in C programming.
The serverside code is good and runs flawlessly.
Its the client side that only returns the string that the server is supposed to send out on the FIRST attempt of running it. After that the code doesnt work anymore and i have to restart my terminal and recompile the code for it to work again.
am i doing it right? did i call the IP of my vps right in my client.c?
This is my host machines client.c code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
// create a socket
int mySocket;
mySocket = socket(AF_INET, SOCK_STREAM, 0);
//specify an address structure for the socket
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(666);
server_address.sin_addr.s_addr = inet_addr("IP OF MY VPS");
int connection_status = connect(mySocket, (struct sockaddr *) &server_address, sizeof(server_address));
//check for error with the connection
if (connection_status == -1) {
printf("There was an error making a connection to the remote socket \n\n");
exit(1);
}
// recieve data from the server
char server_response[256];
recv(mySocket, &server_response, sizeof(server_response), 0);
// pritn out the server's response
printf("The server sent the data: %s\n \n",server_response);
close(mySocket);
return 0;
}
Now here is the code for my VPS's server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
int main()
{
char server_message[256] = "client has connected";
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(666);
server_address.sin_addr.s_addr = INADDR_ANY;
bind(server_socket, (stuct sockaddr*) &server_address,
sizeof(server_address));
listen(server_socekt, 5);
int client_socket;
client_socket = accept(server_socket, NULL, NULL);
send(client_socket, server_message,sizeof(server_message), 0);
close(server_socket);
return 0;
}
note: this code works some times but then most of the time it doesnt
You have no processing loop in the server: each time a client connects, after sending it a message, the server stops listening and terminates.
You can correct the problem in the server:
/* listen for new clients */
listen(server_socket, 5);
while (1)
{
int client_socket;
/* wait for a new client */
client_socket = accept(server_socket, NULL, NULL);
/* send the message */
send(client_socket, server_message,sizeof(server_message), 0);
/* and close only the client socket, not the listening one*/
close(client_socket);
}
/* Once the while loop is finished, you can stop listen (up to you to
change the while loop condition)*/
close(server_socket);
Another thing: you should use perror function to display errors messages, for instance,
int connection_status = connect(mySocket, (struct sockaddr *) &server_address, sizeof(server_address));
//check for error with the connection
if (connection_status == -1) {
perror("connect");
exit(1);
}
will give you this kind of message on error:
connect: Connection refused

Send / receive data over network in C

I have written this program:
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int socket_desc;
struct sockaddr_in adress;
int addrlen;
int new_socket;
int bufsize = 1024;
char *you_sent = "You sent: ";
int main() {
char *buffer = malloc(bufsize);
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
adress.sin_family = AF_INET;
adress.sin_addr.s_addr = INADDR_ANY;
adress.sin_port = htons(7000);
bind(socket_desc, (struct sockaddr *)&adress, sizeof(adress));
listen(socket_desc, 3);
addrlen = sizeof(struct sockaddr_in);
new_socket = accept(socket_desc, (struct sockaddr *)&adress, &addrlen);
while(recv(new_socket,buffer,bufsize,0))
{
printf("I recieved: %s", buffer);
send(new_socket, you_sent, strlen(you_sent), 0);
send(new_socket, buffer, strlen(buffer), 0);
memset(buffer, '\0', sizeof(buffer));
}
}
I can connect to the server with a telnet. And write stuff to the application and recieve data from the application.
But i cannot get my head around how i can connect to this with another c program and send and recieve data from that program.
I have tried this:
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int socket_desc;
struct sockaddr_in adress;
int addrlen;
int new_socket;
char *message_to_send = "Hello world!";
int main() {
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
adress.sin_family = AF_INET;
adress.sin_addr.s_addr = INADDR_ANY;
adress.sin_port = htons(7000);
bind(socket_desc, (struct sockaddr *)&adress, sizeof(adress));
listen(socket_desc, 3);
addrlen = sizeof(struct sockaddr_in);
new_socket = accept(socket_desc, (struct sockaddr *)&adress, &addrlen);
send(new_socket, message_to_send, strlen(message_to_send), 0);
}
A server is like a telephone operator on a switch board. That person does the following:
Sits in front of a phone (i.e. bind to a number)
Waits for it to ring (i.e. listen)
Picks up the phone (i.e. accept)
The person at the other end just wants to make a call to that person. (i.e. connect). The person only needs to go to the phone when a call needs to be made. Therefore not bound to the phone or has to listen for it to ring.
I hope this metaphor helps in your understanding.
PS: The socket part is the phone socket on the wall.
The sequence is the following:
Server side:
Socket creation with the socket syscall;
Binding of the port with the bind syscall;
Listening with the listen syscall (this will enable the backlog queue);
Accepting the incoming connections with the accept syscall
This is a blocking operation: your thread will remain blocked until a connection comes in);
The accept function will return a new file descriptor representing the new connection. You will use this one to send/receive data with the other host, while the original file descriptor (from socket) will be used for new incoming connections.
Client side:
Socket creation with socket;
Connection with connect.
Here you may find some additional resources.

Passing multiple messages from client -> server and server -> client sockets in C

Could someone help identify why my server cannot accept more than one message from the client?
I am attempting to have the flow be like the following:
1. Client sends size of message to server
2. Server receives the size and sends a response back. In this case 0.
3. Client checks response and then writes message to server.
4. Server reads message and prints it out.
The problem I am getting is that the accept() at step 4 is never unblocking.
CLIENT
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(int argc, char *argv[])
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in s_address;
s_address.sin_family = AF_INET;
s_address.sin_port = htons(51717);
s_address.sin_addr.s_addr = INADDR_ANY;
if (connect(sock, (struct sockaddr *) &s_address, sizeof(s_address)) < 0) {
printf("ERROR: Cannot connect()\n");
exit(0);
}
char *org_msg = "Hello";
printf("Writing size of Hello\n");
char msg1[1];
msg1[0] = sizeof(org_msg);
write(sock, msg1, sizeof(msg1));
printf("Waiting for response from server\n");
struct sockaddr_in c_address;
socklen_t c_length = sizeof(c_address);
int new_sock = accept(sock, (struct sockaddr *) &c_address, &c_length);
printf("Reading response from server\n");
char stat[1];
read(new_sock, stat, 1);
if (atoi(stat) == 0) {
printf("Writing Hello to server\n");
write(sock, org_msg, sizeof(org_msg));
}
close(sock);
close(new_sock);
}
SERVER
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(int argc, char *argv[])
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in s_address;
s_address.sin_family = AF_INET;
s_address.sin_port = htons(51717);
s_address.sin_addr.s_addr = INADDR_ANY;
if (bind(sock, (struct sockaddr *) &s_address, sizeof(s_address)) < 0) {
printf("ERROR: Cannot bind()\n");
exit(0);
}
listen(sock, 3);
printf("Waiting for client message\n");
struct sockaddr_in c_address;
socklen_t c_length = sizeof(c_address);
int new_sock = accept(sock, (struct sockaddr *) &c_address, &c_length);
printf("Reading client message\n");
char msg[1];
read(new_sock, msg, 1);
printf("Writing response to client\n");
char stat[1];
stat[0] = '0';
write(new_sock, stat, sizeof(stat));
printf("Waiting for client message\n");
int new_sock2 = accept(sock, (struct sockaddr *) &c_address, &c_length);
printf("Reading client message\n");
char msg2[atoi(msg)];
read(new_sock2, msg2, sizeof(msg2));
printf("MESSAGE: %s\n", msg2);
close(sock);
close(new_sock);
close(new_sock2);
}
You should not call accept() on an already-connected socket. Once you have a connected socket in the server (the socket returned by accept()) you should just keep reading and writing that socket until the connection is closed. The steps for the server should be similar to:
listen_socket = socket(...);
listen(listen_socket, ...);
connected_socket = accept(listen_socket, ...);
read(connected_socket, ...)
write(connected_socket, ...)
read(connected_socket, ...)
write(connected_socket, ...)
...
Similarly the client should just keep reading and writing the socket once it has been connected successfully - the steps for the client should be:
connected_socket = socket(...);
connect(connected_socket, ...);
write(connected_socket, ...);
read(connected_socket, ...);
write(connected_socket, ...);
read(connected_socket, ...);
...
INADDR_ANY works in the server but your client needs to specify what host it's connecting to.
If both are on the same machine, just use 127.0.0.1 or localhost (you'll have to do a transform so that it's the right format)
More information here, but a short answer would be
#define INADDR_LOOPBACK 0x7f000001
and then s_address.sin_addr.s_addr = htonl (INADDR_LOOPBACK)
On the client you try to accept a new connection with the socket you previously connected to the server, which will be bound to a system-chosen port number. The server never tries to connect to the client, so the accept call on the client never returns (actually it may return but with an error, because you never call listen on that socket).
Why not just perform step 3 with the same socket used in the previous steps? If for some reason you do need a new socket, you should create a new socket in the client instead of reusing the previous socket (or call close on the previous socket and then call connect on it again).
BTW if all you need is IPC, sockets are a really bad way to do it. I suggest something like Java RMI.

Resources