socket

原来的网址: http://blog.sina.com.cn/s/blog_6294abe701011tyl.html


对socket服务器海量并发比较感兴趣,从网上搜了一些材料,和大家分享一下:

一、SPServer: 一个基于线程池(包括HAHS和LF)的开源服务器框架

SPServer 是一个实现了半同步/半异步(Half-Sync/Half-Async)和领导者/追随者(Leader/Follower) 模式的服务器框架,能够简化 TCP server 的开发工作。

SPServer 使用 c++ 实现,目前实现了以下功能:
1.封装了 TCP server 中接受连接的功能;
2.使用非阻塞型I/O和事件驱动模型,基于 libevent;
3.对于 HSHA 线程池,由主线程负责处理所有 TCP 连接上的数据读取和发送,因此连接数不受线程数的限制;主线程读取到的数据放入队列,由一个线程池处理实际的业务;
4.对于 LF 线程池,由线程池中的线程轮流获得 leader 角色进行处理;
5.一个 http 服务器框架,即嵌入式 web 服务器。
6.从 0.7 版本开始支持 ssl 

项目主页
[url=http://code.google.com/p/spserver/]http://code.google.com/p/spserver/

下载地址
[url=http://freshmeat.net/redir/spserver/68862/url_tgz/spserver-0.3.src.tar.gz]http://spserver.googlecode.com/files/spserver-0.6.src.tar.gz 
[url=http://code.google.com/p/spserver/downloads/list]http://code.google.com/p/spserver/downloads/list

详细的介绍
[url=http://iunknown.javaeye.com/blog/59804]http://iunknown.javaeye.com/blog/59804

HSHA 模式
[url=http://www.cs.wustl.edu/~schmidt/PDF/HS-HA.pdf]http://www.cs.wustl.edu/~schmidt/PDF/HS-HA.pdf

LF 模式
[url=http://www.cs.wustl.edu/~schmidt/PDF/lf.pdf]http://www.cs.wustl.edu/~schmidt/PDF/lf.pdf

关于 HSHA 和 LF 的一些介绍
[url=http://iunknown.javaeye.com/blog/60414]http://iunknown.javaeye.com/blog/60414

项目中包含一个线程池子项目
http://iunknown.javaeye.com/blog/38544 

以上是从 http://www.chinaunix.net/jh/23/957813.html 中粘贴过来的,有兴趣可以看看这个链接。

 

二、http://www.pudn.com/downloads124/sourcecode/unix_linux/network/detail527666.html

这里有一个线程池+socket的服务器源代码,有兴趣的可以学习一下。

三、linux下最好的io模型是epoll,有点类似于windows下的完成端口,感觉select支持1000个左右就差不多了。要想支持10k以上的连接,需要考虑的问题有很多。
你可以看一下下面这个链接(C10k Problem)。
http://www.kegel.com/c10k.html

四、在网上无意看到一个多线程的Socket服务器端例子,觉得非常不错。特别是其中的线程池的思想,简单而且高效。虽然JDK1.5开始已经自带了线程池包,但该代码不失为学习Socket和多线程的一个好的入门例子。

下面的代码是对该例子的简单整理,补充了注释。

【代码一】PooledConnectionHandler:后台处理类

package  server;

import  java.io.BufferedReader;
import  java.io.FileNotFoundException;
import  java.io.FileReader;
import  java.io.IOException;
import  java.io.InputStreamReader;
import  java.io.PrintWriter;
import  java.net.Socket;
import  java.util.LinkedList;
import  java.util.List;


public   class  PooledConnectionHandler  implements  Runnable {

    

    
protected  Socket connection;

    

    
protected   static  List pool  =   new  LinkedList();

    

    
public  PooledConnectionHandler() {
    }
    
    

    
public   void  run() {
        
while  ( true {
            
//  因为可能有多个线程同时去Pool中取Socket进行处理。
            
//  所以这里我们需同步,防止同一个请求被多次处理
             synchronized  (pool) {
                
while  (pool.isEmpty()) {
                    
try  {
                        pool.wait();
//  没有请求到来则等待
                     catch  (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                
//  从池中取出一个Socket,准备进行处理
                connection  =  (Socket) pool.remove( 0 );
            }
            
//  取到Socket后则不需要同步了,因为此时是Connection是对象
            
//  级属性,在线程内部自己处理,不涉及公共资源的访问
            handleConnection();
        }
    }
    
    

    
public   static   void  processRequest(Socket requestToHandle) {
        
//  因为有可能在向池中塞请求的时候,另外一个线程
        
//  正在从池中取Socket,所以这里需要同步一下
         synchronized  (pool) {
            
//  将来自客户端的请求添加到请求队列末尾
            pool.add(pool.size(), requestToHandle);
            
//  通知其它正在等待的线程有新请求来到,
            
//  此时所有处于wait状态的线程将被唤醒
            pool.notifyAll();
        }
       

    

    
public   void  handleConnection() {
        
try  {
            PrintWriter streamWriter 
=   new  PrintWriter(connection
                    .getOutputStream());
            BufferedReader streamReader 
=   new  BufferedReader(
                    
new  InputStreamReader(connection.getInputStream()));

            String fileToRead 
=  streamReader.readLine();
            BufferedReader fileReader 
=   new  BufferedReader( new  FileReader(
                    fileToRead));

            String line 
=   null ;
            
while  ((line  =  fileReader.readLine())  !=   null )
                streamWriter.println(line);

            fileReader.close();
            streamWriter.close();
            streamReader.close();
        
catch  (FileNotFoundException e) {
            System.out.println(
"" );
        
catch  (IOException e) {
            System.out.println(
""   +  e);
        }
       
}


【代码二】PooledRemoteFileServer:多线程服务器端,负责创建线程池并等待客户端的连接请求

package  server;

import  java.io.IOException;
import  java.net.BindException;
import  java.net.ServerSocket;
import  java.net.Socket;


public   class  PooledRemoteFileServer {

    

    
protected   int  maxConnections;

    

    
protected   int  listenPort;

    

    
protected  ServerSocket serverSocket;

    

    
public  PooledRemoteFileServer( int  aListenPort,  int  maxConnections) {
        listenPort 
=  aListenPort; //  监听端口
         this .maxConnections  =  maxConnections; //  最大同时连接
    }

    

    
public   void  setUpHandlers() {
        
for  ( int   =   0 <  maxConnections; i ++ {
            PooledConnectionHandler currentHandler 
=   new  PooledConnectionHandler();
            
//  线程启动后将一直监控Socket队列,以轮询的方式
            
//  监控是否有新的客户端请求到来,如果有的话则取
            
//  出处理,无的话则继续等待直至请求到来
             new  Thread(currentHandler,  " Handler "   +  i).start();
        }
    }

    

    
public   void  acceptConnections() {
        
try  {
            ServerSocket server 
=   new  ServerSocket(listenPort,  5 );
            Socket incomingConnection 
=   null ;
            
while  ( true {
                incomingConnection 
=  server.accept();
                handleConnection(incomingConnection);
            }
        
catch  (BindException be) {
            System.out.println(
"" );
        
catch  (IOException ioe) {
            System.out.println(
""   +  listenPort);
        }
    }

    

    
protected   void  handleConnection(Socket connectionToHandle) {
        PooledConnectionHandler.processRequest(connectionToHandle);
    }

    
public   static   void  main(String args[]) {
        PooledRemoteFileServer server 
=   new  PooledRemoteFileServer( 1001 3 );
        
//  初始化线程池
        server.setUpHandlers();
        
//  开始在指定端口等待到来的请求
        server.acceptConnections();
    }
}


这个例子的精髓是在PooledConnectionHandler类,它首先创建一个公共的全局“线程池”(LinkList),然后启动线程监控线程池,与此同时服务器端在接收到客户端请求后将请求加到“线程池”中,这两个动作是异步的,在加的时候不允许读,在读得到时候不允许加(通过synchronized关键字控制),而且多个线程之间并不会互相影响,因为其中的connection属性是对象级的。

从这个例子中我们也可以学到在多线程的情况下,哪些变量是必须设置为全局的(static),哪些是必须设置为对象级的:即会被多个线程访问的资源必须设置为全局的,而跟线程处理状态,结果有关的属性一般必须设置为对象级的,以防止互相干扰。

其次就是在多线程情况下,哪些方法是可以设置为static的而不会出现线程安全的问题,哪些方法是不能设置为静态方法的:如果方法是属于控制流程,通知,派发的,那么一般可以设置为静态的。因为这些方法一般不需要多个,一个就够了。就如同控制器只要一个就够了。而业务逻辑实现方法一般不能设置为静态的,因为静态方法不能引用对象变量(非静态变量),但业务逻辑通常是需要针对不同的用户做出不同的处理的,所以几乎可以肯定的说是绝对会出现对象变量的。
五、

linux下多线程socket监听的c程序(例子)  

 

#include<stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 8888

void *yourfunction(void *connect_fd)
{
int connfd = *((int *)connect_fd);
              。。。。
} //在这里面直接对connfd调用read和write函数就可以和客户端收发数据了。


int main(void)
{
int sockfd, n, connfd;
pthread_t tid;
struct sockaddr_in servaddr;

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
  perror("socket:");
  exit(1);
}

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);

n = bind(sockfd, (struct sockaddr *)&servaddr,sizeof(servaddr));
if (n == -1)
{
  perror("bind:");
  exit(1);
}

n = listen(sockfd, 20);
if (n == -1)
{
  perror("listen:");
  exit(1);
}

while (1)
{
  connfd = accept(sockfd, (struct sockaddr*)&servaddr, NULL);
  pthread_create(&tid, NULL,yourfunction, (void *)&connfd);
}

return 0;
}
暂时就这些吧,希望对学习这一块的朋友有所帮助。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值