Skip to content

Instantly share code, notes, and snippets.

@daqing
Created September 18, 2011 03:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save daqing/1224706 to your computer and use it in GitHub Desktop.
Save daqing/1224706 to your computer and use it in GitHub Desktop.
my first 'hello world' example for socket programming
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <signal.h>
#define TRUE 1
void sigchld_handler(int s) {
while(waitpid(-1, NULL, WNOHANG) > 0);
}
int main(void) {
// create a TCP Stream socket
int s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0) return -1;
// set socket option: reuseaddr
int on = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
return -1;
}
// create an address and bind the socket to it
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(1986);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
char *bind_address = "127.0.0.1";
if (inet_aton(bind_address, &sa.sin_addr) == 0) {
printf("invalid bind address\n");
close(s);
return -1;
}
// bind socket to sa
if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
printf("can't bind on this address.\n");
close(s);
return -1;
}
// ok, socket has been created and binded to an address, now listen on this socket now...
if (listen(s, 511) == -1) { // this magic 511 backlog value is fron nginx
printf("ERROR: listen: %s\n", strerror(errno));
close(s);
return -1;
}
// register signal handler
struct sigaction sig_a;
sig_a.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sig_a.sa_mask);
sig_a.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sig_a, NULL) == -1) {
printf("register signal handler failed.\n");
return -1;
}
// all right, now we listen for new connections on this socket and handle them in a infinite loop
struct sockaddr_in peer_addr;
socklen_t addr_len = sizeof(peer_addr);
while(TRUE) {
printf("trying to accept connections, pid: %d...\n", getpid());
int new_socket = accept(s, (struct sockaddr*)&peer_addr, &addr_len);
if (new_socket == -1) {
perror("can't accept connection on socket");
exit(-1);
}
printf("server: accepted connection from %s\n", inet_ntoa(peer_addr.sin_addr));
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(0);
}
if (pid == 0) {
// in child process
close(s);
printf("child process pid: %d\n", getpid());
printf("Child process takes over the socket handling task...\n");
char *response = "[message from server] hello, world!\n";
int len = strlen(response);
int bytes_sent = send(new_socket, response, len, 0);
if (bytes_sent == -1) {
perror("write error on socket!\n");
close(new_socket);
exit(-1);
} else if (bytes_sent == 0) {
// ?
} else if (bytes_sent > 0) {
printf("Great! message was sent to client!\n");
printf("bytes to send: %d\n", len);
printf("actually sent: %d\n", bytes_sent);
}
printf("ok, nothing interesting to to, we're going to close the socket...\n");
close(new_socket);
printf("socket closed, exit...\n");
exit(0);
} else if (pid > 0) {
// in parent
printf("[parent] in parent process...\n");
close(new_socket);
}
}
return 0;
}
@sroshangh
Copy link

Well Done!
May I ask you write a bit about how I can execute the code!!!
I compiled it to a.out. Then, I wrote in a Linux terminal:
./a.out
It wrote : trying to accept connections, pid: 16099...
and the cursor blinks frequently.
each time a new pid,
I dont know what I should do next, I'm new at socket programming, please help me,\

even I opened another terminal and tried to create a telnet but it was refused
I wrote : telnet localhost 16099

I'm looking forward to your help
Thank you in advance

@corwin-of-amber
Copy link

At this point, this program is the first hit in Google for "socket hello world C". So in case you got here, a few comments:

  • The listening port in this program is 1986 (see line 35).
  • This server will only listen to connections from localhost -- that is, not from any other host on your network. This is due to lines 37-42. If you want it to accept any connection, remove them.
  • Notice that it is wrong to pass INADDR_ANY though htons. It is benign here because on most systems, INADDR_ANY is the constant zero, which is unaffected by htons. (htons changes the byte order of a 16-bit word.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment