呈现一张基本的socket阻塞式模型,如下图:
一: 对于一对一的进行C/S回射:
服务端(server.c):
1 #include<unistd.h>
2 #include<stdio.h>
3 #include<string.h>
4 #include<stdlib.h>
5 #include<netinet/in.h>
6 #include<sys/socket.h>
7 #include<sys/types.h>
8 #include<error.h>
9
10 #define ERR_EXIT(m) \
11 do{ \
12 perror(m); \
13 exit(1); \
14 }while(0)
15
16 int
17 main (void)
18 {
19 int sock, conn;
20 if ((sock = socket (PF_INET, SOCK_STREAM, 0)) < 0)
21 ERR_EXIT ("socket");
22 struct sockaddr_in sockaddr;
23 memset (&sockaddr, 0, sizeof (sockaddr));
24 sockaddr.sin_family = AF_INET;
25 sockaddr.sin_port = htons (5528);
26 sockaddr.sin_addr.s_addr = htonl (INADDR_ANY);
27 if (bind (sock, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0)
28 ERR_EXIT ("Bind");
29 if (listen (sock, SOMAXCONN) < 0)
30 ERR_EXIT ("Listen");
31 struct sockaddr_in client;
32 memset (&client, 0, sizeof (client));
33 socklen_t addrlen = sizeof (client);
34 if ((conn = accept (sock, (struct sockaddr *) &client, &addrlen)) < 0)
35 ERR_EXIT ("Accept");
36 char sed[1024], recv[1024];
37 while (fgets (sed, sizeof (sed), stdin) != NULL || 1 == 1)
38 {
39 if (strlen (sed) > 0)
40 write (conn, sed, sizeof (sed));
41 if (read (conn, recv, sizeof (recv)) > 0)
42 {
43 fputs (recv, stdout);
44 if (strcmp (recv, "exit") == 0)
45 break;
46 write (conn, recv, sizeof (recv));
47 }
48 else
49 ERR_EXIT ("read...");
50 }
51 close (conn);
52 close (sock);
53 return 0;
54 }
客户端(client.c):
1 #include<unistd.h>
2 #include<stdio.h>
3 #include<string.h>
4 #include<error.h>
5 #include<netinet/in.h>
6 #include<stdlib.h>
7 #include<sys/socket.h>
8 #include<sys/types.h>
9
10 #define ERR_EXIT( m ) \
11 do{ \
12 perror(m); \
13 exit(1); \
14 }while(0);
15
16 int
17 main (void)
18 {
19 int socketid, conn;
20
21 if ((socketid = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
22 ERR_EXIT ("socket");
23
24 struct sockaddr_in server_addr;
25 memset (&server_addr, 0, sizeof (server_addr));
26
27 server_addr.sin_family = AF_INET;
28 server_addr.sin_port = htons (5528);
29 server_addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
30 if ((conn =
31 connect (socketid, (struct sockaddr *) &server_addr,
32 sizeof (server_addr))) < 0)
33 ERR_EXIT ("connect");
34 char sendbuf[1024], recivebuf[1024];
35 while (fgets (sendbuf, sizeof (sendbuf), stdin) != NULL)
36 {
37 write (socketid, sendbuf, sizeof (sendbuf));
38 read (socketid, recivebuf, sizeof (recivebuf));
39 fputs (recivebuf, stdout);
40 if (strcmp (recivebuf, "exit") == 0)
41 {
42 ERR_EXIT ("exit");
43 break;
44 }
45 }
46 close (conn);
47 close (socketid);
48 return 0;
49 }
相关的makefile文件
1 makefile文件:
2
3 .SUFFIXES: .o.c
4 .PHONY: clean
5 .PHONY: start
6
7 CC =gcc
8 SRC =server.c
9 OBJS =$(SRC:.c =.o)
10 BIN = Server
11
12 start:
13 $(CC) -o $(BIN) $(OBJS)
14
15 .o.c:
16 $(CC) -g -Wall $@ -c $<
17 clean:
18 rm -f $(OBJS)
但是上述虽然满足了基本的socket套路,但是当我们关闭服务可执行程序时,在开启就会出现地址被占用,解决此等问题,需再加上一个setsockopt()函数,对齐进行设定。
详细可以去查询man帮助(man setsockopt)
代码:
1 int on = 1;
2 if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
3 {
4 ERR_EXIT ("setsockopt");
5 }
6
7
8 if (bind (sock, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0)
9 ERR_EXIT ("Bind");
二: 利用进程进行并行socket阻塞式连接:
客户端和makefile文件和上面一样,只是将socket的服务端,修改为调用进程来进行多并发连接即可!
服务端(server.c):
1 #include<unistd.h>
2 #include<stdio.h>
3 #include<string.h>
4 #include<stdlib.h>
5 #include<netinet/in.h>
6 #include<sys/socket.h>
7 #include<sys/types.h>
8 #include<error.h>
9
10 #define ERR_EXIT(m) \
11 do{ \
12 perror(m); \
13 exit(1); \
14 }while(0)
15
16
17 void
18 print (int conn){
19
20 char sed[1024], recv[1024];
21 while (fgets (sed, sizeof (sed), stdin) != NULL || 1 == 1)
22 {
23 if (strlen (sed) > 0)
24 write (conn, sed, sizeof (sed));
25 if (read (conn, recv, sizeof (recv)) > 0)
26 {
27 fputs (recv, stdout);
28 if (strcmp (recv, "exit") == 0)
29 break;
30 write (conn, recv, sizeof (recv));
31 }
32 else
33 ERR_EXIT ("read...");
34 }
35 close (conn);
36 }
37
38 int
39 main (void)
40 {
41 int sock, conn;
42 if ((sock = socket (PF_INET, SOCK_STREAM, 0)) < 0)
43 ERR_EXIT ("socket");
44 struct sockaddr_in sockaddr;
45 memset (&sockaddr, 0, sizeof (sockaddr));
46 sockaddr.sin_family = AF_INET;
47 sockaddr.sin_port = htons (5528);
48 sockaddr.sin_addr.s_addr = htonl (INADDR_ANY);
49
50 int on = 1;
51 if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
52 {
53 ERR_EXIT ("setsockopt");
54 }
55
56
57 if (bind (sock, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0)
58 ERR_EXIT ("Bind");
59
60 if (listen (sock, SOMAXCONN) < 0)
61 ERR_EXIT ("Listen");
62
63 struct sockaddr_in client;
64 memset (&client, 0, sizeof (client));
65 socklen_t addrlen = sizeof (client);
66 pid_t pid ;
67
68 while (1)
69 {
70 if((conn = accept (sock, (struct sockaddr *) &client, &addrlen)) < 0)
71 ERR_EXIT ("Accept");
72 pid = fork ();
73 if (pid == -1)
74 ERR_EXIT ("fork");
75 else if (pid == 0){
76 close (sock);
77 print (conn);
78 }
79 else
80 close (conn);
81 }
82 close (sock);
83 return 0;
84 }