一、什么是网络io?
网络io就是计算机在网络的环境下进行输入和输出操作,这些操作包含:发送请求、接受响应、下载文件、传输数据等。
二、简单的网络io长什么样子?
一个简单的网络io包含服务端和客户端,首先客户端与服务端建立链接,然后客户端通过该链接向服务端发送请求,服务端根据该请求做出不同的响应。
三、实现:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <pthread.h>
void *client_thread(void* arg)
{
int clientfd = *(int *)(arg);
while(1)
{
char buff[1024] = {0};
int count = recv(clientfd, buff, 1024, 0);
if (count == 0)
{
close(clientfd);
break;
}
printf("Recv: %s.\n", buff);
count = send(clientfd, buff, 1024, 0);
}
}
int main()
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(2000);
if (-1 == bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr)))
{
printf("bind failed:%s.\n", strerror(errno));
}
if (-1 == listen(sockfd, 10))
{
printf("listen failed:%s.\n", strerror(errno));
}
printf("listen finished.\n");
struct sockaddr_in clientaddr;
socklen_t len = sizeof(clientaddr);
while(1)
{
int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &len);
pthread_t tid;
pthread_create(&tid, NULL, client_thread, &clientfd);
}
return 0;
}
以上代码主要做了四件事情:
1、创建服务器的socket套接字;
2、将socket与指定IP地址和端口进行绑定:
结构体Struct sockaddr_in的属性sin_addr.s_addr表示网络地址,指一个专门用于接受或发起网络请求的IP地址。因为这里是作为服务器,并且要接受所有请求,所以使用宏INADDR_ANY,表示接受所有IPV4的请求。
如果要专门结构某一个客户端的请求,这里写指定客户端的IP;如果是客户端,那么这里应该写指定链接的服务器的IP地址。
3、让服务器进行监听,接受客户端的连接请求:
listen的作用是把服务器设置的套接字(函数的参数1)设置为监听状态,这个套接字专门用来处理客户端的连接请求。
4、接收连接请求,创建数据传输的套接字:
当accept被调用时,会从监听的套接字里检查有没有新的连接请求。如果有新的连接请求,就创建一个新的套接字给这个连接,专门用来进行客户端与服务器的数据传输。
四、基于一请求一线程的理解:
1、服务端的套接字分为两类:专门用来监听的套接字,专门用来传输数据的套接字。
2、用于监听的套接字:只能绑定一个端口,并且只有这一个。
3、用于传输数据的套接字:只要有一个请求,就可以为其创建一个套接字,数量取决于客户端个数。
五、一请求一线程的网络io的缺点:
1、资源消耗大:
- 在高并发场景下,每个请求都分配一个线程,导致线程数量迅速增加。
- 系统的资源是有限的,无法无限制地增加线程数量。
- 大量的线程切换会增加系统的开销,影响整体性能
2、线程管理复杂:
- 线程的创建、销毁和调度都需要进行细致的管理。
- 线程间的同步和通信复杂,有死锁、竞态条件等问题。
3、资源浪费:
- 在某些情况下,线程可能处于等待状态,等待网络IO的完成或其他资源的释放。
- 在这种情况下,线程并没有被有效利用,而是浪费了系统资源
其他:
netstat -anop | grep 端口号 查看端口号情况