Linux-网络编程(day13)
一、基于TCP的网络编程(续day12)
二、并发服务器
三、基于UDP的网络编程
一、基于TCP的网络编程(续day12)
1、昨天的例子客户端只能向指定的服务器端发送数据,可以利用主函数参数传递命令行参数,从而接收任意服务器地址。同时也可以实现两台机器之间的通信(可以事先使用ping命令查看是否通)
2、也可以使用while循环在客户端不断接收数据输入,知道特定字符结束输入关闭通讯,如使用fgets,或gets
#if 0
...
#endif
可以进行条件注释
基于TCP的服务器:
#include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> int main() { int listenfd = socket (AF_INET, SOCK_STREAM, 0); if (listenfd == -1) { perror ("socket"); exit (EXIT_FAILURE); } struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons (8888); addr.sin_addr.s_addr = INADDR_ANY; if (bind (listenfd, (struct sockaddr*)&addr, sizeof (addr)) == -1) { perror ("bind"); exit (EXIT_FAILURE); } if (listen (listenfd, 1024) == -1) { perror ("listen"); exit (EXIT_FAILURE); } struct sockaddr_in addrcli = {}; socklen_t addrlen = sizeof (addrcli); int connfd = accept (listenfd, (struct sockaddr*)&addrcli, &addrlen); if (connfd == -1) { perror ("accept"); exit (EXIT_FAILURE); } printf ("服务器已接受来自%s:%hu客户机的连接请求\n", inet_ntoa (addrcli.sin_addr),ntohs (addrcli.sin_port)); char buf[1024]; ssize_t rcvd = recv (connfd, buf, sizeof (buf), 0); if (rcvd == -1) { perror ("recv"); exit (EXIT_FAILURE); } if (rcvd == 0) { printf ("客户机已关闭连接\n"); exit (EXIT_FAILURE); } buf[rcvd] = '\0'; printf ("客户端说:%s\n", buf); printf ("服务器说:"); gets (buf); ssize_t sent = send (connfd, buf, strlen (buf) * sizeof (buf[0]), 0); if (sent == -1) { perror ("send"); exit (EXIT_FAILURE); } if (close (listenfd) == -1) { perror ("close"); exit (EXIT_FAILURE); } if (close (connfd) == -1) { perror ("close"); exit (EXIT_FAILURE); } return 0; }
基于TCP的客户端:
#include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> int main() { int listenfd = socket (AF_INET, SOCK_STREAM, 0); if (listenfd == -1) { perror ("socket"); exit (EXIT_FAILURE); } struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons (8888); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect (listenfd, (struct sockaddr*)&addr, sizeof (addr)) == -1) { perror ("connect"); exit (EXIT_FAILURE); } char buf[1024] = "你好,服务器"; printf ("客户端说:%s\n", buf); ssize_t sent = send (listenfd, buf, strlen (buf) * sizeof (buf[0]), 0); if (sent == -1) { perror ("send"); exit (EXIT_FAILURE); } ssize_t rcvd = recv (listenfd, buf, sizeof (buf), 0); if (rcvd == -1) { perror ("recv"); exit (EXIT_FAILURE); } buf[rcvd] = '\0'; printf ("服务器说:%s\n", buf); if (close (listenfd) == -1) { perror ("close"); exit (EXIT_FAILURE); } return 0; }
上述服务器只能给一个客户端提供服务,这就需要后面讲到的并发来解决。
可以使用setsockopt(2)来设置socket属性,或者getsockopt(2)来获取socket属性。
二、并发服务器
1、使用线程实现并发服务器
2、多路复用计数实现并发服务器
select(2)、poll(2)等
3、使用多进程实现并发服务器
在这里需要分清楚,父进程,子进程的作用,以及fork的时机。