Created
September 18, 2011 03:50
-
-
Save daqing/1224706 to your computer and use it in GitHub Desktop.
my first 'hello world' example for socket programming
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
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
thoughhtons
. It is benign here because on most systems,INADDR_ANY
is the constant zero, which is unaffected byhtons
. (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
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