web服务器
代码
例子
服务器端
初始化,socket版本
-
调用socket创建一个套接字(应用层和传输层的接口)
-
调用bind函数绑定套接字,指定绑定的IP地址和端口号
-
调用listen函数使服务器监听状态,使套接字变为可接受请求状态(可被动链接)
-
调用accept函数等待客户端的连接请求
-
recv,send接受/发送数据
-
send()
(1)第一个参数指定发送端套接字描述符;
(2)第二个参数指明一个存放应用程序要发送数据的缓冲区;
(3)第三个参数指明实际要发送的数据的字节数;
(4)第四个参数一般置0
7.recv()
(1)第一个参数指定接收端套接字描述符;
(2)第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
(3)第三个参数指明buf的长度;
(4)第四个参数一般置0。
8.关闭服务器
客户端
- 2(connect).5.8.
浏览器输入url后,首先和web服务器建立tcp连接,
recv / send接收发送数据
然后浏览器发送http请求报文, web服务器响应处理这个报文,
然后给他回复一个响应,然后服务器主动断开连接
后来,写了一个客户端来,通过终端与服务器进行通信,将客户端与服务器通信写进循环,实现了客户端与服务器不断的相互发送信息,
(B)因为只有一个服务器,在面对多个客户端时,服务器必须等待第一个客户端发送信息才能接受其他客户端发来的信息。
由此,我使用并发服务器,通过创建子进程,使得多个客户端能随时发信息给服务器,也就是说,每有一个请求,服务器就创建一个进程来处理对应的事件,
并发服务器模型的缺点是:在同时有很多客户端连接时,服务器在每一个客户连接时就会新建一个进程,最后会产生很多进程,这样会占用很多系统资源
(C)引入:可不可以就只实现一个单进程服务器就可以处理多个客户端连接的程序
I/O多路复用模型:实现一个线程可以监视多个文件句柄;一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;没有文件句柄就绪时会阻塞应用程序,交出cpu(多路是指网络连接,复用指的是同一个线程)(优势:由于I/O多路复用是在单一进程的上下文中的,因此每个逻辑流程都能访问该进程的全部地址空间,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销;缺点是编程复杂度高)
增加一个中间层来解决,同样,为了避免这里cpu的空转,我们不让这个线程亲自去检查流中是否有事件,而是引进了一个代理(一开始是select,后来是poll),这个代理很牛,它可以同时观察许多流的I/O事件,如果没有事件,代理就阻塞,线程就不会挨个挨个去轮询了
四、I/O复用实现流程(进程阻塞于select(),而select检测相应的描述符集,如果有就绪的描述符,则退出阻塞,然后进程判断就绪的描述符并作相应的处理;)
1、定义描述符集合,使用FD_ZERO()函数初始化描述符集合,然后将监听套接字描述符加入描述符集合中。
2、使用一个永真循环进行轮询。
3、在每次循环过程中,首先调用select函数将需要监听的描述符集合通知内核,然后使用FD_ISSET()函数判断监听套接字是否已经准备好,若已经准备好,调用accept函数获取已连接套接字,并将已连接套接字放进描述符集合中,然后更新已连接套接字个数和下一个循环调用select函数的第一个参数的值。接着使用在一个for循环中(循环参数为已连接套接字个数,相当于对每个已连接套接字都去查询是否已经准备好)FD_ISSET函数接着判断已连接套接字准备好,若准备完毕,则进行收发数据,若数据收发完毕,返回数据大小为0,则关闭已连接套接字,使用FD_CLR清理掉这个描述符在描述符集合中。以上完成后,则进入下一个循环,接着轮询。
大概:select函数之后我们就能让内核去监听是否有请求,如果有的话就通知我们的服务器去做相关处理即可
问题:
如果我们让服务器每处理一个客户端连接是sleep10秒,模拟一下耗时操作,发现在服务器在处理每一个客户端连接时是串行在处理,这样肯定不行的啊。所以服务器在处理多个客户连接时,不能阻塞于某一个客户的处理或与其相关的某个函数的调用,否则会导致服务器被挂起,拒绝为其他所有客户服务,这就是所谓的拒绝服务型攻击,他就是对服务器做某些动作,导致服务器不能为其他合法客户服务。解决办法有:(1)使用非阻塞I/O;(2)为每个客户建立一个单独的线程或进程来处理客户需求(此时并非在连接建立时创建,而是在做实际的处理时才创建);(3)为I/O设置一个超时时间
用select实现并发服务器端
利用一个“监听者”,当有客户端发出连接请求及客户端发送信息时,才会和服务器连接。
多线程优点
无需跨进程边界;
程序逻辑和控制方式简单;
所有线程可以直接共享内存和变量等;
线程方式消耗的总资源比进程方式好;
jemter压力测试
2000条并发数
实现服务器与客户端间的通信 - 可以实现HTTP请求中的GET方法 - 提供静态网页浏览功能,如可浏览:HTML页面,无格式文本,常见图像格式等 - 提供可以传递参数的动态网页浏览功能 - 可以检查一些明显错误报告给客户端 - 在服务器端可输出HTTP响应的相关信息
建立一个socket。
2.创建结构体地址,初始化这个地址为本机地址(“127.0.0.1”)。
3.然后把socket和这个地址绑定。(bind函数),因为采用TCP形式通信,所以绑定后为,ip地址+端口号,这里设置的是8888。
4.上面创建好的地址是我收东西的地址,我开始监听这个端口(listen)。
5.while(1)循环监听,创建一个新的地址,放accept里面可以显示地址来自哪里,这里accept相当于接收到了传过来的socket。
6.返回信息,有很多返回信息的方法,有read,write什么的,我初学觉得recv和send还是比较好用的。一个接收客户端传来的信息,一个向发送方发送信息。
7.这个程序放在linux运行,运行成功后,打开浏览器访问本机地址。
http://localhost:8888/
socket编程为什么要选择AF_INET
为什么网络socket编程是阻塞的?因为非阻塞轮询占CPU,用多线程和IO复用
检测URL
游戏eaxyx
鼠标交互MouseHit
游戏配乐mciSendString
绘图解决闪屏问题 BeginBatchDraw()
FlushBatchDraw()//更新一次画面_2,解决画面闪的问题,需要配合BeginBatchDraw函数使用
cleardevice();//清除之前的画迹