I'm trying to make a simple Socket program and I'm right now able to create a server socket, bind the server socket to a port and listen for incoming connections after which, when I try to start with the accepting of the connection, nothing gets printed out.
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[]){
char buffer[1024] = {0};
char *mes = "peepeepoopoo";
struct sockaddr_in server;
int addr_size = sizeof(server);
//xxxxxxxx Creating the socket xxxxxxxx
int sockfd_server = socket(AF_INET, SOCK_STREAM, 0);
int client_socket;
if(sockfd_server < 0){
printf("Socket not created\n");
return -1;
}
puts("Socket created\n");
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8070);
//xxxxxxxx Binding xxxxxxx
if(bind(sockfd_server,(struct sockaddr*)&server, sizeof(server)) < 0){
printf("failed to bind\n");
return -1;
}
puts("binding completed\n");
//xxxxxxxx Listening xxxxxxxx
if (listen(sockfd_server,3) < 0)
{
printf("Listening error\n");
}
puts("Listening\n");
// none of the statements prints, almost like its frozen.
int new_Socket = accept(sockfd_server, (struct sockaddr*)&server, (socklen_t*)&addr_size);
if(new_Socket < 0){
printf("could not accept socker\n");
return -1;
}
puts("accepted\n");
int val = read(new_Socket,buffer, 1024);
printf("%s\n",buffer);
send(new_Socket, mes, strlen(mes), 0);
return 0;
}
What do I do to fix this?
accept
If no pending connections are present on the queue, and the socket is not marked as nonblocking, accept() blocks the caller until a connection is present.
Question: Do you connect a client to your server?
addr_size is declared as int, yet passed as an argument while casting it to socklen_t. Can you guarantee that sizeof(int) == sizeof(socklen_t)?
You read into buffer but do not null-terminate it before passing it to printf with the format specifier %s.
Related
I'm trying to launch multiple servers, at once, in a c program. For the sake of simplicity let's say 5 servers.
If I understand well the sockets, each of them must be listening to a different IP socket address (different PORT, different IP interface address).
I thought to do that inside a loop, incrementing port number by i at each turn. Here's my current code just to launch one server. I know it's possible with bash by launching the same process in background, but in C I really don't know how to do that and if it's even possible
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
long PORT;
int main(int argc, char const *argv[])
{
/* 1. Open a socket
2. Bind to a address(and port).
3. Listen for incoming connections.
4. Accept connections
5. Read/Send
*/
int listenerSocket; /* socket for accepting connections */
int clientSocket; /* socket connected to client */
struct sockaddr_in server;
struct sockaddr_in client; /* client address information */
char buf[100]; /* buffer for sending & receiving data */
int errnum;
listenerSocket = socket(AF_INET, SOCK_STREAM, 0);
if(listenerSocket == -1){
perror("erreur lors de la création du socket");
}
PORT = strtol(argv[1], NULL, 10);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port= htons(PORT);
if (bind(listenerSocket, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
puts("Server waiting for connection...");
while(1){
if (listen(listenerSocket, 5) < 0){
perror("listen failed");
exit(EXIT_FAILURE);
}
int c = sizeof(client);
if((clientSocket = accept(listenerSocket, (struct sockaddr*) &client, &c)) < 0){
puts("error accepting the request");
perror("Accept()");
}
puts("connection accepted");
while(1){
if( recv(clientSocket, buf, sizeof(buf), 0) < 0) {
errnum = errno;
perror("Recv()");
printf("val printed by errno: %d\n",errno);
}
printf("Message : %s\n", buf);
}
if (send(clientSocket, buf, sizeof(buf), 0) < 0)
{
perror("Send()");
exit(7);
}
close(clientSocket);
close(listenerSocket);
printf("Server ended successfully\n");
exit(0);
}
I have written a basic client server code in c socket programming using the TCP/IP protocol but i cant figure out how to make it connect to different clients and send/receive different data to and from them as a function to the client (meaning if its the first client send him that data and if its that client send him the other data) and so on.
This is the only results i have found were sending the same data to different clients.
Current Server:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
int main() {
char server_message[100] = {0};
int server_socket = 0;
int client_socket = 0;
struct sockaddr_in server_address;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
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, 2);
client_socket = accept(server_socket, NULL, NULL);
printf("Please enter a massage:");
fgets(server_message, 100, stdin);
send(client_socket, server_message, sizeof(server_message), 0);
close(server_socket);
return 0;
}
By using original code from geeksforgeeks and Myst comment we can solve it.
You have one server that serves on local host 127.0.0.1, and can have multiple clients for this example i assume 5 clients are enough.
Run server once, and run many client to connect seprately to that server.
Server.c
// Server side C/C++ program to demonstrate Socket programming
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#define PORT 8080
#define STRING_SIZE 100
#define BUFFER_SIZE 100
int main(int argc, char const *argv[])
{
int server_fd, new_socket[5], valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char *hello = "Hello from server";
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
for (int i=0;i<5;i++){
if ((new_socket[i] = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
valread = read(new_socket[i], buffer, 1024);
printf("%s\n", buffer);
char send_buf[STRING_SIZE] = "hello";
char buf[BUFFER_SIZE]={0};
sprintf(buf, "%d", i);
strcat(send_buf, buf);
send(new_socket[i], send_buf, strlen(send_buf), 0);
//printf("Hello message sent\n");
}
return 0;
}
Client.c
// Client side C/C++ program to demonstrate Socket programming
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define PORT 8080
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
send(sock , hello , strlen(hello) , 0 );
//printf("Hello message sent\n");
valread = read( sock , buffer, 1024);
printf("%s\n", buffer);
return 0;
}
Run
After compiling codes with gcc client.c -o client and gcc server.c -o server
Open one terminal for server and start server by run ./server.
Now you can connect many client [up to 5] to it by running ./client.
this maybe is a simple question but I'm trying to just read a server response using the sockets API adapting the code from Geeks for Geeks [site]1, when I try to read the data, it becomes blocked forever in the valread = read(server_fd, buffer, 2048); line, and doesn't execute any of the prints. Am I doing something wrong?
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
int send_request() {
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[512] = {0};
char *hello = "Hello from server";
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
// CONNECT TO HOST
struct hostent *he;
char* host = "www.columbia.edu";
he = gethostbyname(host);
if(!he) {
printf("Host doesn't exist!\n");
return 0;
}
address.sin_family = AF_INET;
bcopy(he->h_addr, &address.sin_addr, sizeof(struct in_addr));
address.sin_port = htons(80);
if(connect(server_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_in)) < 0) {
printf("Error in the connection");
return 0;
}
valread = read(server_fd, buffer, 2048);
printf("%s\n", buffer);
printf("%d\n", valread);
printf("%d\n", errno);
return 0;
}
int main(int argc, char const *argv[]) {
send_request();
return 0;
}
You are connecting to an HTTP server. The HTTP protocol specifies that the client (that is, the side that makes the connection to the server) must send a request first. You aren't sending a request, so the server is not going to send you a reply.
Also, this is a bug:
valread = read(server_fd, buffer, 2048);
printf("%s\n", buffer);
The %s format specifier can only be used with C-style strings. It can't be used for arbitrary data. For one thing, how would it know how many bytes to output? The only place that information is currently contained is in valread, and you didn't pass it to printf.
I'm using C to implement a simple client-server retrieval system with Linux socket. I've now successfully connect the remote server, but when I close the connection, the server went down, i.e. the server program stopped.
What should I do avoid this?
here's sample of my code:
server:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
int main(void)
{
int optval;
socklen_t optlen = sizeof(optval);
char str[100] = "";
int listen_fd, conn_fd;
struct sockaddr_in servaddr;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
// check if on
getsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen);
printf("keep alive is %s\n", (optval? "ON" : "OFF"));
// set it on
optval = 1;
optlen = sizeof(optval);
setsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
printf("done, check again.\n");
printf("keep alive is %s\n", (optval? "ON" : "OFF"));
bzero( &servaddr, sizeof(servaddr));
// set appropriate protocol and port number (15792)
// the htons() function converts the unsigned short integer
// from host byte order to network byte order.
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(15792);
// Bind a name to a socket
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
// listening for incoming connection
listen(listen_fd, 10);
// accept a connection on a socket
conn_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
do
{
// set str to null
bzero(str, 100);
// Read from a file descriptor (linux all)
read(conn_fd,str,100);
// print the received message
// printf("Received: %s\n",str);
if (!strcmp(str, "GET TIME\n"))
{
bzero(str, 100);
time_t clocks;
clocks = time(NULL);
sprintf(str, "%s", ctime(&clocks));
write(conn_fd, str, strlen(str));
//close(conn_fd);
}
else
{
bzero(str, 100);
strcpy(str, "ERROR: No such command.\n");
write(conn_fd, str, strlen(str));
//close(conn_fd);
}
} while (1);
}
client:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char **argv)
{
// declare necessary variables
int sockfd;
char recv[1024] = "";
char command[100] = "";
struct sockaddr_in servaddr;
if (argc != 2)
{
printf("usage: %s <ip address>\n", argv[0]);
exit(EXIT_FAILURE);
}
// create a socket with the appropriate protocol
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("ERROR: Failed create cosket.\n");
exit(EXIT_FAILURE);
}
// Set all the socket structures with null values.
bzero(&servaddr, sizeof servaddr);
// set appropriate protocol and port number (1999)
// The htons() function converts the unsigned short integer
// hostshort from host byte order to network byte order.
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(15792);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, argv[1], &(servaddr.sin_addr)) <= 0)
{
printf("ERROR: Wrong ip address.\n");
exit(EXIT_FAILURE);
}
// attempt to connect to a socket
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
printf("ERROR: Failed at connect.\n");
exit(EXIT_FAILURE);
}
else
{
printf("------ connect successfull ------\n");
}
do
{
printf("> ");
fgets(command, 100, stdin);
write(sockfd, command, strlen(command));
if (!strcmp(command, "QUIT\n"))
{
close(sockfd);
break;
}
// print the receive stuff
read(sockfd, recv, sizeof(recv));
fputs(recv, stdout);
bzero(recv, 1024);
} while (1);
}
In your server code, the accept() function must be called in the do-while loop:
// listening for incoming connection
listen(listen_fd, 10);
do
{
// accept a connection on a socket
conn_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
...
close(conn_fd);
} while(1);
my question here is, why server ended if I close the connection from
the client.
Because then the blocking read call will return the value 0 indicating the connection was closed, which you promptly ignore. You then try (and fail) to compare the received data (which you have none) to the string and you will attempt to write the error message to the (now disconnected) client which will raise the SIGPIPE error which terminates your application.
– Some programmer dude
I am beginner in socket programming and reading Linux Network Programming book. I decided to implement client-server connection as shown in the book. Server program is run on Ubuntu 14.04 machine and client code is run from Mac machine. The server code is the following
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
const char message[] = "hello, world\n";
int main()
{
int sock = 0;
int port = 0;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
fprintf(stderr, "failed\n");
else
printf("connection is establisshed\n");
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY );
server.sin_port = 3500;
int status = bind(sock, (struct sockaddr*) &server, sizeof(server));
if (status == 0)
printf("connection completed\n");
else
printf("problem is encountered\n");
status = listen(sock, 5);
if (status == 0)
printf("app is ready to work\n");
else
{
printf("connection is failed\n");
return 0;
}
while (1)
{
struct sockaddr_in client = { 0 };
int sclient = 0;
int len = sizeof(client);
int childSocket = accept(sock, (struct sockaddr*) &client, &len);
if (childSocket == -1)
{
printf("cannot accept connection\n");
close(sock);
break;
}
write(childSocket, message, strlen(message));
close(childSocket);
}
return 0;
}
As for client side i wrote the following code
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(int argc, char* argv[])
{
int sock = 0;
int port = 0;
struct sockaddr_in servaddr;
sock = socket(AF_INET, SOCK_STREAM, 0);
int status = 0;
char buffer[256] = "";
if (sock == -1)
{
printf("could not establish connection\n");
exit(1);
}
port = 3500;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(argv[1]);
servaddr.sin_port = htons(port);
status = connect(sock, (struct sockaddr*) &servaddr, sizeof(servaddr));
if (status == 0)
printf("connection is established successfully\n");
else
{
printf("could not run the app\n");
exit(1);
}
status = read(sock, buffer, sizeof(buffer));
if (status > 0)
printf("%d: %s", status, buffer);
close(sock);
return 0;
}
To get IP address of client machine I run ifconfig from terminal an get inet_addr 192.168.1.165 value. Now when I pass that address string as command line argument I get message that app is not running message. There is problem with address that I got, as I understand. So what is the problem?
Thanks in advance
Most probably the server does not listen on the port you are assuming, that is 3500.
To fix this, change this line:
server.sin_port=3500
to be
server.sin_port = htons(3500);
(To monitor which process is listing on which address:port you might like to use the netstat command line tool. In your case probably using the options -a -p -n )
Also on recent systems accept() expects a pointer to socklen_t as last parameter, so change this
int len=sizeof(client);
to be
socklen_t len = sizeof client; /* sizeof is an operator, not a function¨*/