I need help understanding the bind function in C socket programming - c

I'm trying to really understand sockets, so I am learning it in C. This is the server code.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
char server_message[255] = "You have reached the server!";
//create server socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
//define server addr
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
//Bind socket to IP and Port
bind(server_socket, (struct sockaddr*) &server_address, sizeof(server_address));
listen(server_socket, 5);
int client_socket;
client_socket = accept(server_socket, NULL, NULL);
//send message
send(client_socket, server_message, sizeof(server_message), 0);
//close socket
close(server_socket);
return 0;
}
In the bind function, this part is needed to specify the address
(struct sockaddr*) &server_address
I read the man page, and it does say it has to be this way, the code also runs, but I don't understand this syntax. What is happening in this part of the code. I know * is used to declare pointers, and & refers to the memory address of the variable. I just can't put it all together.

Related

Connection between two computers using sockets in C. (TCP)

I have been following this tutorial to learn something about socket programming in C. Everythink is working just fine, but it only works on one PC. I would like to know how to host server on one PC (I will use rpi4 in future) and connect to the server with client on another PC.
This is code for server, when client connect to server, it sends "You have reached the server" message to client.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char const *argv[])
{
char server_message[256] = "You have reached the server";
int server_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
bind(server_socket, (struct sockaddr*) &server_address, sizeof(server_address));
listen(server_socket, 0);
int client_socket;
client_socket = accept(server_socket, NULL, NULL);
send(client_socket, server_message, sizeof(server_message), 0);
close(server_socket);
return 0;
}
here is client.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char const *argv[])
{
int network_socket = 0;
network_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
int connection_status = connect(network_socket, (struct sockaddr *) &server_address, sizeof(server_address));
if (connection_status == -1)
{
printf("Connection Error!");
return 0;
}
char server_response[256];
recv(network_socket, server_response, sizeof(server_response), 0);
printf("Data from server %s\n", server_response);
close(network_socket);
return 0;
}
I naively tried to replace INADDR_ANY with inet_addr("myip"); but it doesnt work.
Thanks for any help!
(Also sorry my first post on sof, hope everything is ok)
server_address.sin_addr.s_addr = INADDR_ANY;
is wrong, you need to soecify the address of the server, either
by getting the address manually, hardcoded or by some discovery protocol
(lookup gethostbyname()

use sockets to read an RFID device from the network using C

I found an RFID reader with a finger print reader that I would like to use. I tried to use sockets to listen to the port, but I'm unsure on how can I do it properly. The device does not have any labels, so I cannot find data from manufacturer on how to establish the connection. The devices works as I have tested with another software used for clocking in, so the device has now an IP address assigned that I'm able to ping. I have tried a socket server program to listen to the port, but I'm not getting anything when I read the RFID tags. How can I read data from the device when it is connected to the network and store the data?
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
main(){
char server_message[256] = "You have reached the server";
//create the server socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
//define the server address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
//bind the socket to our specified IP and port
bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address));
listen(server_socket, 5);
int client_socket;
client_socket = accept(server_socket,NULL,NULL);
char server_response[256];
recv(server_socket, &server_response, sizeof(server_response), 0);
//print out server's response
printf("The server sent the data: %s\n", server_response);
//send the message
send(client_socket, server_message, sizeof(server_message), 0);
//close the socket
close(server_socket);
return 0;
}

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

bind Invalid argument

I'm playing with the unix sockets. The code compiles fine but I get the following message on execute
Invalid argument
Here is the code i use. It's pretty simple I think
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#define PORT 7000
int main(){
int socket_desc;
struct sockaddr_in address;
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if(socket_desc == -1)
perror("Create socket");
/* type of socket created in socket() */
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
/* set port */
address.sin_port = htons(PORT);
while(1) {
/* bind the socket to the port specified above */
if(bind(socket_desc,(struct sockaddr *)&address, sizeof(address)) < 0) {
perror("Error");
exit(-1);
}
}
return 0;
}
The problem is that you're trying to bind more than once -- what's with the while(1) loop?
while(1) {
/* bind the socket to the port specified above */
if(bind(socket_desc,(struct sockaddr *)&address, sizeof(address)) < 0) {
perror("Error");
exit(-1);
}
}
bind() succeeds the first time, and on the subsequent call it fails with EINVAL, which means (from man 2 bind):
[EINVAL] socket is already bound to an address and the protocol does not support binding to a new address. Alternatively, socket may have been
shut down.
As a side note, it's probably a good idea to zero out the sockaddr prior to passing it in:
#include <string.h>
/* ... */
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

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.

Resources