socket编程与利用进程进行多并行连接

时间:2022-05-05
本文章向大家介绍socket编程与利用进程进行多并行连接,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

       呈现一张基本的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 }