Penguin
Blame: NetworkProgramming
EditPageHistoryDiffInfoLikePages
Annotated edit history of NetworkProgramming version 14, including all changes. View license author blame.
Rev Author # Line
14 AristotlePagaltzis 1 InNeedOfRefactor
2
12 MattBrown 3 This is to describe how to write networking programs in [C] using the [BSD] Socket Layer [API]. This mostly applies to almost all other languages with only minor modifications. This is an updated version of the page which is designed to be non-AddressFamily specific, for the old version see NetworkProgrammingOld. SocketAddressing may also be useful.
10 PerryLorier 4
5 !!!General structure for a server setup
6 The various steps of setting up a server are:
7 # Creating a socket of the correct type, with socket(2)
8 # bind(2) the socket to a port (and optionally an interface)
9 # listen(2) on that port
10 # accept(2) client connections
11
12 getaddrinfo(3) will sort out the correct parameters for socket(2) and bind(2), making things fairly simple. An example below:
13
14 * First find our what to bind to.
15 #include <sys/socket.h>
16 #include <sys/types.h>
17 #include <netdb.h>
18
19 int bind_service(char *service,int socktype) {
20 struct addrinfo hints;
21 struct addrinfo *result;
22 struct addrinfo *result_iter;
23 int serverfd;
24
25 hints.ai_flags=AI_PASSIVE;
26 hints.ai_family=PF_UNSPEC; /* We don't care if it's PF_INET, or PF_INET6 */
27 hints.ai_socktype=SOCK_STREAM /* 0 for any type, SOCK_STREAM for streams, SOCK_DGRAM for datagrams */
28 hints.ai_protocol=0; /* 0 for any protocol, use getprotobyname(3) to find a protocol */
29 hints.ai_addrlen=0;
30 hints.ai_addr=NULL;
31 hints.ai_canonname=NULL; /* Unused */
32 hints.ai_next=NULL;
33
34 ret=getaddrinfo(NULL,service,&hints,&result);
35 if (ret!=0) {
36 fprintf(stderr,"getaddrinfo failed: %s",gai_strerror(ret));
37 return -1;
38 }
39
40 for(result_iter = result;result_iter;result_iter=result_iter->next) {
41 serverfd = socket(result_iter->ai_family,result_iter->ai_socktype,result_iter->ai_protocol);
42 if (serverfd<0) {
43 perror("socket");
44 continue;
45 }
46 if (bind(serverfd,result_iter->address,result_iter->addrlen)<0) {
47 perror("bind");
48 continue;
49 }
50 break;
51 }
52
53 if (!result_iter) {
54 fprintf(stderr,"Unable to bind to service \"%s\"\n",service);
55 freeaddrinfo(result);
56 return -1;
57 }
58
59 freeaddrinfo(result);
60 return serverfd;
61 }
62
63 void do_client(int clientfd)
64 {
65 char *message = "Hello World\n";
66 write(clientfd,message);
67 close(clientfd);
68 }
69
70 int main(int argc,char **argv)
71 {
72 int serverfd;
73
74 serverfd = bind_service("hello",SOCK_STREAM);
75
76 if (serverfd<0) {
77 return 1;
78 }
79
80 if (listen(serverfd,8)<0) {
81 perror("listen");
82 return 1;
83 }
84
85 for (;;) {
86 int clientfd;
87
88 clientfd = accept(serverfd);
89
90 if (clientfd<0) {
91 perror("accept");
92 /* Note that accept tends to fail reasonably often, so don't abort the server here */
93 }
94
95 if (fork()==0) {
96 /* Client Thread */
97 close(serverfd);
98 do_client(clientfd);
99 exit(0);
100 }
101 else {
102 /* Server Thread */
103 close(clientfd);
104 }
105 }
106
107 close(serverfd);
11 PerryLorier 108 }
109
110 !!!A General Client Implementation
111 * Create a socket of the correct type with socket(2)
112 * connect(2) it to a correct address
113
114 A simple client implementation:
115 #include <sys/types.h>
116 #include <sys/socket.h>
117 #include <netdb.h>
118
119 int create_client_connection(char *hostname,char *service)
120 {
121 struct addrinfo hints;
122 struct addrinfo result;
123 struct addrinfo result_iter;
124 int ret;
125 int clientfd;
126
127 hints.ai_flags=0;
128 hints.ai_family=PF_UNSPEC;
129 hints.ai_socktype=SOCK_STREAM;
130 hints.ai_protocol=0;
131 hints.ai_addrlen=0;
132 hints.ai_address=NULL;
133 hints.ai_canonname=NULL;
134
135 ret=getaddrinfo(hostname,service,&hints,&result);
136 if (ret!=0) {
137 fprintf("getaddrinfo failed: %s",gai_strerror(ret));
138 return -1;
139 }
140
141 for(result_iter = result; result ; result_iter=result_iter->next) {
142 clientfd=socket(result_iter->ai_family,result_iter->ai_socktype,result_iter->ai_protocol);
143 if (clientfd<0) {
144 perror("socket");
145 continue;
146 }
147 if (bind(clientfd,result_iter->ai_address,result_iter->ai_addrlen)<0) {
148 perror("bind");
149 close(clientfd);
150 continue;
151 }
152 break;
153 }
154
155 if (!result_iter) {
156 return -1;
157 }
158
159 return clientfd;
160 }
161
162 int main(int argc,char **argv)
163 {
164 int clientfd;
13 AristotlePagaltzis 165 char buffer[[65535];
11 PerryLorier 166 int length;
167
168 clientfd=create_client_connection("localhost","hello");
169
170 if (clientfd<0) {
171 return 1;
172 }
173
174 len=read(clientfd,buffer,sizeof(buffer));
175
176 if (len<0) {
177 perror("read");
178 close(clientfd);
179 return 1;
180 }
181
182 /* Write it to stdout (fd1) */
183 write(1,buffer,len);
184
185 close(clientfd);
10 PerryLorier 186 }