
package MyKeFudaun;
import javaioBufferedReader;
import javaioBufferedWriter;
import javaioIOException;
import javaioInputStreamReader;
import javaioOutputStreamWriter;
import javanetSocket;
import javanetUnknownHostException;
public class KeFuDuan {
public static void main(String[] args) {
KeFuDuan kf = new KeFuDuan();
kfstart();
}
public void start(){
Socket sco;
String ss= "";
try {
sco = new Socket("127001",8866);
KeFuduanJie kf = new KeFuduanJie(sco);
KeFuWuFasong kfs = new KeFuWuFasong(sco);
kfstart();
kfsstart();
//scoclose();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
eprintStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
eprintStackTrace();
}
}
}
class KeFuduanJie extends Thread{
Socket soc;
String ss;
BufferedReader br;
public KeFuduanJie(Socket soc){
try {
thissoc = soc;
br = new BufferedReader(new InputStreamReader(socgetInputStream()));
} catch (IOException e) {
eprintStackTrace();
}
}
//负责接受服务端来的信息
public void run(){
while(true){
//接受服务器端来的信息
try {
ss = brreadLine();
Systemoutprintln("服务器---->客服端: "+ss);
} catch (IOException e) {
// TODO Auto-generated catch block
eprintStackTrace();
}
}
}
}
//向服务器发送东西
class KeFuWuFasong extends Thread{
Socket soc;
BufferedWriter bw;
BufferedReader brr;
public KeFuWuFasong(Socket soc){
thissoc = soc;
try {
brr =new BufferedReader(new InputStreamReader(Systemin));
bw = new BufferedWriter(new OutputStreamWriter(socgetOutputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
eprintStackTrace();
}
}
public void run(){
while(true){
//向服务器发送请求
try {
bwwrite(brrreadLine());
bwnewLine();
bwflush();// 或者用bwclose()
} catch (IOException e) {
// TODO Auto-generated catch block
eprintStackTrace();
}
}
}
}
服务器端:
package MyKeFudaun;
import javaioBufferedReader;
import javaioBufferedWriter;
import javaioIOException;
import javaioInputStreamReader;
import javaioOutputStreamWriter;
import javanetServerSocket;
import javanetSocket;
public class Server {
public static void main(String[] args) {
Server server = new Server();
serverstart();
}
public void start(){
try { //服务器端打开端口
ServerSocket server = new ServerSocket(4499);
Socket socket = null;
ServerToClientThread stct = null;
while(true){
socket = serveraccept(); //迎接(接收)客户端的Socket访问
stct = new ServerToClientThread(socket); //分配一个新线程负责和信赖的Socket沟通
stctstart();
}
} catch (IOException e) {
eprintStackTrace();
}
}
}
package MyKeFudaun;
import javaioBufferedReader;
import javaioIOException;
import javaioInputStreamReader;
import javanetSocket;
public class ServerReceiveFromClient extends Thread{
Socket socket;
BufferedReader br;
String s;
public ServerReceiveFromClient(Socket socket){
thissocket = socket;
try {
br = new BufferedReader(new InputStreamReader(socketgetInputStream()));
} catch (IOException e) {
eprintStackTrace();
}
}
public void run(){
while(true){
try {
s = brreadLine();
Systemoutprintln(socketgetInetAddress()getHostAddress()+"发送了:"+s);
} catch (Exception e) {
eprintStackTrace();
}
}
}
}
package MyKeFudaun;
import javaioBufferedReader;
import javaioBufferedWriter;
import javaioIOException;
import javaioInputStreamReader;
import javaioOutputStreamWriter;
import javanetSocket;
public class ServerToClientThread extends Thread{
Socket socket;
BufferedReader br;
BufferedWriter bw;
String s;
//建立的同时,和客户端的Socket建立输入、输出流
public ServerToClientThread(Socket socket){
thissocket = socket;
try {
bw = new BufferedWriter(new OutputStreamWriter(socketgetOutputStream()));
} catch (IOException e) {
eprintStackTrace();
}
}
public void run(){
ServerReceiveFromClient srfc = new ServerReceiveFromClient(socket);
srfcstart();
while(true){
try {
bwwrite("欢迎光临。");
bwnewLine();
bwflush();
Threadsleep(101000);
} catch (IOException e) {
eprintStackTrace();
} catch (InterruptedException e) {
eprintStackTrace();
}
}
}
}Nginx会按需同时运行多个进程:一个主进程(master)和几个工作进程(worker),配置了缓存时还会有缓存加载器进程(cache loader)和缓存管理器进程(cache manager)等。Nginx主要通过“共享内存”的机制实现进程间通信。主进程以root用户身份运行,而worker、cache loader和cache manager均应以非特权用户身份运行。
在工作方式上,Nginx分为单工作进程和多工作进程两种模式。在单工作进程模式下,除主进程外,还有一个工作进程,工作进程是单线程的;在多工作进程模式下,每个工作进程包含多个线程。Nginx默认为单工作进程模式。多线程是一个软件进程中使用多条处理线程
分布式是同一套软件中的数据在多个软件客户端、服务端进行处理。可以是在同一台电脑或服务器端开多个软件,但更多是指通过网络连接多台客户端与服务端进行数据处理。是把海量数据分布在不同的计算机或软件中分别处理的一种软件结构。
并行是指两个或者多个事件在同一时刻发生
并发是指两个或多个事件在同一时间间隔内发生。多线程请求并发这个服务器已经做好了(比如tomcat),你不需要考虑,action的处理看你要用的是哪个框架了,如果是struts2 不用考虑多线程,如果是原始的servlet必须考虑并发的临界资源问题。
如果你是想自己实现一个容器,咱们在令当讨论服务程序最为关键的设计是并发服务模型,当前有以下几种典型的模型:
- 单进程服务,使用非阻塞IO
使用一个进程服务多个客户,通常与客户通信的套接字设置为非阻塞的,阻塞只发生在select()、poll()、epoll_wait()等系统调用上面。这是一种行之有效的单进程状态机式服务方式,已被广泛采用。
缺点是它无法利用SMP(对称多处理器)的优势,除非启动多个进程。此外,它尝试就绪的IO文件描述符后,立即从系统调用返回,这会导致大量的系统调用发生,尤其是在较慢的字节传输时。
select()本身的实现也是有局限的:能打开的文件描述符最多不能超过FD_SETSIZE,很容易耗尽;每次从select()返回的描述符组中扫描就绪的描述符需要时间,如果就绪的描述符在末尾时更是如此(epoll特别彻底修复了这个问题)。
- 多进程服务,使用阻塞IO
也称作 accept/fork 模型,每当有客户连线时产生一个新的进程为之服务。这种方式有时是必要的,比如可以通过 *** 作系统获得良好的内存保护,可以以不同的用户身份运行程序,可以让服务运行在不同的目录下面。但是它的缺点也很明显:进程比较占资源,进程切换开销太大,共享某些信息比较麻烦。Apache 13就使用了这种模型,MaxClients数很容易就可以达到。
- 多线程服务,使用阻塞IO
也称之 accept/pthread_create模型,有新客户来时创建一个服务线程而不是服务进程。这解决了多进程服务的一些问题,比如它占用资源少,信息共享方便。但是麻烦在于线程仍有可能消耗光,线程切换也需要开销。
- 混合服务方式
所谓的混合服务方式,以打破服务方和客户方之间严格的1:1关系。基本做法是:
新客户到来时创建新的工作线程,当该工作线程检测到网络IO会有延迟时停止处理过程,返回给Server一个延迟处理状态,同时告诉 Server被延迟的文件描述符,延迟超时时间。Server会在合适的时候返回工作线程继续处理。注意这里的工作线程不是通过 pthread_create()创建的,而是被包装在专门用于处理延迟工作的函数里。
这里还有一个问题,工作线程如何检测网络IO会有延迟?方法有很多,比如设置较短的超时时间调用poll(),或者甚至使用非阻塞IO。如果是套接字,可以设置SO_RCVTIMEO和SO_SNDTIMEO选项,这样更有效率。
除了延迟线程,Server还应提供了未完成线程的支持。
如有有特别耗费时间的 *** 作,你可以在完成部分工作后停止处理,返回给Server一个未完成状态。这样Server会检查工作队列是否有别的线程,如果有则让它们运行,否则让该工作线程继续处理,这可以防止某些线程挨饿。
典型的一个混合服务模型开源实现ServerKit
Serverkit的这些线程支持功能可简化我们的服务程序设计,效率上应该也是有保证的。
2 队列(queue)
ServerKit提供的队列是一个单向链表,队列的存取是原子 *** 作,如果只有一个执行单元建议不要用,因为原子 *** 作的开销较大。
3 堆(heap)
malloc()分配内存有一定的局限,比如在多线程的环境里,需要序列化内存分配 *** 作。ServerKit提供的堆管理函数,可快速分配内存,可有效减少分配内存的序列化 *** 作,堆的大小可动态增长,堆有引用计数,这些特征比较适合多线程环境。目前ServerKit堆的最大局限是分配单元必须是固定大小。
4 日志记录
日志被保存在队列,有一个专门的线程处理队列中的日志记录:它或者调用syslog()写进系统日志,或者通过UDP直接写到远程机器。后者更有效。
5 读写锁
GNU libc也在pthreads库里实现了读写锁,如果定义了__USE_UNIX98就可以使用。不过ServerKit还提供了读写锁互相转换的函数,这使得锁的应用更为d性。比如拥有读锁的若干个线程对同一个hash表进行检索,其中一个线程检索到了数据,此时需要修改它,一种办法是获取写锁,但这会导致释放读锁和获取写锁之间存在时间窗,另一种办法是使用ServerKit提供的函数把读锁转换成写锁,无疑这种方式更有效率。
除了以上这些功能,ServerKit还提供了数据库连接池的管理(当前只支持MySQL)和序列化(Sequences),如感兴趣可参见相关的API文档。
二、ServerKit服务模块编写
ServerKit由3部分组成:server程序,负责加载服务模块、解析配置文件、建立数据库连接池;libserver,动态链接库,提供所有功能的库支持,包括server本身也是调用这个库写的;API,编程接口,你编写的服务模块和ServerKit框架进行对话的接口。
ServerKit需要libConfuse解析配置文件,所以出了安装ServerKit,还需要安装libConfuse。关于libConfuse可参考 >
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)