C socket cheatsheet¶
Get host via gethostbyname
¶
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int ret = -1, i = 0;
struct hostent *h_ent = NULL;
struct in_addr **addr_list = NULL;
if (argc != 2) {
printf("Usage: COMMAND [name]\n");
goto End;
}
h_ent = gethostbyname(argv[1]);
if (h_ent == NULL) {
printf("gethostbyname fail. %s", hstrerror(h_errno));
goto End;
}
printf("Host Name: %s\n", h_ent->h_name);
addr_list = (struct in_addr **)h_ent->h_addr_list;
for (i=0; addr_list[i] != NULL; i++) {
printf("IP Address: %s\n", inet_ntoa(*addr_list[i]));
}
ret = 0;
End:
return ret;
}
output:
$ cc -g -Wall -o gethostbyname gethostbyname.c
$ ./gethostbyname localhost
Host Name: localhost
IP Address: 127.0.0.1
$ ./gethostbyname www.google.com
Host Name: www.google.com
IP Address: 74.125.204.99
IP Address: 74.125.204.105
IP Address: 74.125.204.147
IP Address: 74.125.204.106
IP Address: 74.125.204.104
IP Address: 74.125.204.103
Transform host & network endian¶
#include <stdio.h>
#include <stdint.h>
#include <arpa/inet.h>
static union {
uint8_t buf[2];
uint16_t uint16;
} endian = { {0x00, 0x3a} };
#define LITTLE_ENDIANNESS ((char)endian.uint16 == 0x00)
#define BIG_ENDIANNESS ((char)endian.uint16 == 0x3a)
int main(int argc, char *argv[])
{
uint16_t host_short_val = 0x01;
uint16_t net_short_val = 0;
uint32_t host_long_val = 0x02;
uint32_t net_long_val = 0;
net_short_val = htons(host_short_val);
net_long_val = htonl(host_long_val);
host_short_val = htons(net_short_val);
host_long_val = htonl(net_long_val);
if (LITTLE_ENDIANNESS) {
printf("On Little Endian Machine:\n");
} else {
printf("On Big Endian Machine\n");
}
printf("htons(0x%x) = 0x%x\n", host_short_val, net_short_val);
printf("htonl(0x%x) = 0x%x\n", host_long_val, net_long_val);
host_short_val = htons(net_short_val);
host_long_val = htonl(net_long_val);
printf("ntohs(0x%x) = 0x%x\n", net_short_val, host_short_val);
printf("ntohl(0x%x) = 0x%x\n", net_long_val, host_long_val);
return 0;
}
output:
# on little endian machine
$ ./a.out
On Little Endian Machine:
htons(0x1) = 0x100
htonl(0x2) = 0x2000000
ntohs(0x100) = 0x1
ntohl(0x2000000) = 0x2
# on big endian machine
$ ./a.out
On Big Endian Machine
htons(0x1) = 0x1
htonl(0x2) = 0x2
ntohs(0x1) = 0x1
ntohl(0x2) = 0x2
Basic TCP socket server¶
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define BUF_SIZE 1024
#define isvalidsock(s) (s > 0 ? 1 : 0 )
static int port = 5566;
int main(int argc, char *argv[])
{
int ret = -1;
int s = -1;
int c = -1;
socklen_t clen = 0;
ssize_t len = 0;
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
const int on = 1;
char buf[BUF_SIZE] = {0};
/* set socket host and port */
bzero(&s_addr, sizeof(s_addr));
s_addr.sin_family = AF_INET;
s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
s_addr.sin_port = htons(port);
/* create socket */
s = socket(AF_INET, SOCK_STREAM, 0);
if (!isvalidsock(s)) {
printf("Create socket fail\n");
goto Error;
}
/* set sockopt */
if (0 > setsockopt(s, SOL_SOCKET,
SO_REUSEADDR, &on, sizeof(on))) {
printf("setsockopt fail\n");
goto Error;
}
/* bind address and port */
if (0 > bind(s, (struct sockaddr *) &s_addr,
sizeof(s_addr))) {
printf("bind socket fail\n");
goto Error;
}
/* listen */
if (0 > listen(s, 10)) {
printf("listen fail\n");
goto Error;
}
for(;;) {
clen = sizeof(c_addr);
c = accept(s, (struct sockaddr *)&c_addr, &clen);
if (!isvalidsock(c)) {
printf("accept error\n");
continue;
}
bzero(buf, BUF_SIZE);
if (0 > (len = recv(c, buf, BUF_SIZE-1, 0))) {
close(c);
}
send(c, buf, BUF_SIZE-1, 0);
close(c);
}
ret = 0
Error:
if (s >= 0){
close(s);
}
return ret;
}
output:
$ ./a.out &
[1] 63546
$ nc localhost 5566
Hello Socket
Hello Socket
Basic UDP socket server¶
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#define EXPECT_GE(i, e, ...) \
if (i < e) {__VA_ARGS__}
#define EXPECT_SUCCESS(ret, fmt, ...) \
EXPECT_GE(ret, 0, \
printf(fmt, ##__VA_ARGS__); goto End;)
#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif
int main(int argc, char *argv[])
{
int ret = -1;
int sockfd = -1;
int port = 5566;
char buf[BUF_SIZE] = {};
struct sockaddr_in s_addr = {};
struct sockaddr_in c_addr = {};
socklen_t s_len = 0;
/* create socket */
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
EXPECT_SUCCESS(sockfd, "create socket fail. %s\n", strerror(errno));
/* set socket addr */
bzero((char *) &s_addr, sizeof(s_addr));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(port);
s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
s_len = sizeof(c_addr);
/* bind */
ret = bind(sockfd, (struct sockaddr *)&s_addr, sizeof(s_addr));
EXPECT_SUCCESS(ret, "bind fail. %s\n", strerror(errno));
for(;;) {
bzero(buf, sizeof(buf));
ret = recvfrom(sockfd, buf, sizeof(buf), 0,
(struct sockaddr *)&c_addr, &s_len);
EXPECT_GE(ret, 0, continue;);
ret = sendto(sockfd, buf, ret, 0,
(struct sockaddr *)&c_addr, s_len);
}
ret = 0;
End:
if (sockfd >= 0) {
close(sockfd);
}
return ret;
}
output:
$ cc -g -Wall -o udp_server udp_server.c
$ ./udp_server &
[1] 90190
$ nc -u 192.168.55.66 5566
Hello
Hello
UDP
UDP
Event driven socket via select
¶
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#define BUF_SIZE 1024
#define isvalidsock(s) (s > 0 ? 1 : 0)
#define PORT 5566
int socket_init(void)
{
struct sockaddr_in s_addr;
int sfd = -1;
int ret = -1;
const int on = 1;
bzero(&s_addr, sizeof(s_addr));
s_addr.sin_family = AF_INET;
s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
s_addr.sin_port = htons(PORT);
sfd = socket(AF_INET, SOCK_STREAM, 0);
if (!isvalidsock(sfd)) {
printf("create socket error\n");
goto Error;
}
if (0 > setsockopt(
sfd, SOL_SOCKET,
SO_REUSEADDR, &on, sizeof(on))) {
printf("setsockopt error\n");
goto Error;
}
if (0 > bind(sfd,
(struct sockaddr *)&s_addr,
sizeof(s_addr))) {
printf("bind error\n");
goto Error;
}
if (0 > listen(sfd, 10)) {
printf("listen network error\n");
goto Error;
}
ret = sfd;
Error:
if (ret == -1) {
if (sfd >=0) {
close(sfd);
}
}
return ret;
}
int main(int argc, char *argv[])
{
int ret = -1;
int sfd = -1;
int cfd = -1;
ssize_t len = 0;
struct sockaddr_in c_addr;
int i = 0;
int rlen = 0;
char buf[BUF_SIZE] = {0};
socklen_t clen = 0;
fd_set wait_set;
fd_set read_set;
if (-1 == (sfd = socket_init())) {
printf("socket_init error\n");
goto Error;
}
FD_ZERO(&wait_set);
FD_SET(sfd, &wait_set);
for (;;) {
read_set = wait_set;
if (0 > select(FD_SETSIZE, &read_set,
NULL, NULL, NULL)) {
printf("select get error\n");
goto Error;
}
for (i=0; i < FD_SETSIZE; i++) {
if (!FD_ISSET(i, &read_set)) {
continue;
}
if (i == sfd) {
clen = sizeof(c_addr);
cfd = accept(sfd,
(struct sockaddr *)&c_addr, &clen);
if (!isvalidsock(cfd)) {
goto Error;
}
FD_SET(cfd, &wait_set);
} else {
bzero(buf, BUF_SIZE);
if (0 > (rlen = read(i, buf, BUF_SIZE-1))) {
close(i);
FD_CLR (i, &wait_set);
continue;
}
if (0 > (rlen = write(i, buf, BUF_SIZE-1))) {
close(i);
FD_CLR (i, &wait_set);
continue;
}
}
}
}
ret = 0;
Error:
if (sfd >= 0) {
FD_CLR(sfd, &wait_set);
close(sfd);
}
return ret;
}
output: (bash 1)
$ ./a.out &
[1] 64882
Hello
Hello
output: (bash 2)
$ nc localhost 5566
Socket
Socket
socket with pthread¶
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <pthread.h>
#define EXPECT_GE(i, e, ...) \
if (i < e) { __VA_ARGS__; }
#define EXPECT_SUCCESS(ret, fmt, ...) \
EXPECT_GE(ret, 0, printf(fmt, ##__VA_ARGS__); goto End)
#define SOCKET(sockfd, domain, types, proto) \
do { \
sockfd = socket(domain, types, proto); \
EXPECT_SUCCESS(sockfd, "create socket fail. %s", strerror(errno)); \
} while(0)
#define SETSOCKOPT(ret, sockfd, level, optname, optval) \
do { \
int opt = optval;\
ret = setsockopt(sockfd, level, optname, &opt, sizeof(opt)); \
EXPECT_SUCCESS(ret, "setsockopt fail. %s", strerror(errno)); \
} while(0)
#define BIND(ret, sockfd, addr, port) \
do { \
struct sockaddr_in s_addr = {}; \
struct sockaddr sa = {}; \
socklen_t len = 0; \
ret = getsockname(sockfd, &sa, &len); \
EXPECT_SUCCESS(ret, "getsockopt fail. %s", strerror(errno)); \
s_addr.sin_family = sa.sa_family; \
s_addr.sin_addr.s_addr = inet_addr(addr); \
s_addr.sin_port = htons(port); \
ret = bind(sockfd, (struct sockaddr *) &s_addr, sizeof(s_addr)); \
EXPECT_SUCCESS(ret, "bind fail. %s", strerror(errno)); \
} while(0)
#define LISTEN(ret, sockfd, backlog) \
do { \
ret = listen(sockfd, backlog); \
EXPECT_SUCCESS(ret, "listen fail. %s", strerror(errno)); \
} while(0)
#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif
void *handler(void *p_sockfd)
{
int ret = -1;
char buf[BUF_SIZE] = {};
int c_sockfd = *(int *)p_sockfd;
for (;;) {
bzero(buf, sizeof(buf));
ret = recv(c_sockfd, buf, sizeof(buf) - 1, 0);
EXPECT_GE(ret, 0, break);
send(c_sockfd, buf, sizeof(buf) - 1, 0);
}
EXPECT_GE(c_sockfd, 0, close(c_sockfd));
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
int ret = -1, sockfd = -1, c_sockfd = -1;
int port = 9527;
char addr[] = "127.0.0.1";
struct sockaddr_in c_addr = {};
socklen_t clen = 0;
pthread_t t;
SOCKET(sockfd, AF_INET, SOCK_STREAM, 0);
SETSOCKOPT(ret, sockfd, SOL_SOCKET, SO_REUSEADDR, 1);
BIND(ret, sockfd, addr, port);
LISTEN(ret, sockfd, 10);
for(;;) {
c_sockfd = accept(sockfd, (struct sockaddr *)&c_addr, &clen);
EXPECT_GE(c_sockfd, 0, continue);
ret = pthread_create(&t, NULL, handler, (void *)&c_sockfd);
EXPECT_GE(ret, 0, close(c_sockfd); continue);
}
End:
EXPECT_GE(sockfd, 0, close(sockfd));
ret = 0;
return ret;
}
output:
# console 1
$ cc -g -Wall -c -o test.o test.c
$ cc test.o -o test
$ ./test &
[1] 86601
$ nc localhost 9527
Hello
Hello
# console 2
$ nc localhost 9527
World
World