`

socket编程(三)--服务器端实现多线程处理客户端请求并且将客户请求放在连接池中

阅读更多

需求:通socket编程(一)的需求

该实例中,客户端可能会有多个,服务器的处理器也会有多个,该情形类似于消费者在超市结账的过程,

假设固定有5个收银员,而消费者不确定:

如果开始没有消费者来结账,那么所有的收银员都处于等待状态;

如果有一个消费者来结账,那么随即会有一个收银员来处理,其他的收银员仍处于等待状态;

如果有大于一个小于6个的消费者来结账,那么收银员都会随即进行处理;

如果有大于5个的消费者在等待,就需要排队了(这也就是要说的连接池即客户端的请求链接放置的地方,把客户请求放在这个池子里)

 

客户端:

package com.socket.clientsocket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class Sclient {

	/**
	 * @param args
	 */
	
	protected BufferedReader socketReader;
	protected PrintWriter socketWriter;
	protected String hostIp;
	protected int hostPort;
	
	
	public Sclient(String ahostIp,int ahostPort){
		this.hostIp = ahostIp;
		this.hostPort = ahostPort;
		
	}
	public void setUpConnection(){
	
		try {
			//1.创建Socket,建立连接
			Socket socket = new Socket(hostIp,hostPort);
			//2.获取输入流和输出流,并进行封装
			socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			socketWriter = new PrintWriter(socket.getOutputStream());
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	public void tearDownConnection(){
		
		try {
			socketReader.close();
			socketWriter.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
	}
	//根据需求,对流进行处理
	public String getFile(String fileNameToGet){
		StringBuffer sb = new StringBuffer();
		socketWriter.println(fileNameToGet);
		socketWriter.flush();
		String line = null;
		try {
			while((line = socketReader.readLine()) != null){
				sb = sb.append(line + "\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return sb.toString();
	}
	public static void main(String[] args) {
		//创建客户端
		Sclient client = new Sclient("198.27.0.166",8200);
		//建立连接
		client.setUpConnection();
		//需求操作
		String content = client.getFile("c:\\log.txt");
		//关闭连接
		client.tearDownConnection();
	}

}

 服务器端:

package com.socket.poolSocketServer;

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

public class PooledRemoteFileServer {

	/**
	 * @param args
	 */
	protected int maxConnections;
    protected int listenPort;
    protected ServerSocket serverSocket;
    public PooledRemoteFileServer(int aListenPort, int maxConnections) {
        listenPort = aListenPort;
        this.maxConnections = maxConnections;
    }
    public void acceptConnections() {
        try {
            ServerSocket server = new ServerSocket(listenPort, 5);
            Socket incomingConnection = null;
            while (true) {
                incomingConnection = server.accept();
                handleConnection(incomingConnection);
            }
        } catch (BindException e) {
            System.out.println("Unable to bind to port " + listenPort);
        } catch (IOException e) {
            System.out.println("Unable to instantiate a ServerSocket on port: " + listenPort);
        }
    }
    protected void handleConnection(Socket connectionToHandle) {
        PooledConnectionHandler.processRequest(connectionToHandle);
    }
    public static void main(String[] args) {
        PooledRemoteFileServer server = new PooledRemoteFileServer(3000, 3);
        server.setUpHandlers();
        server.acceptConnections();
    }
    public void setUpHandlers() {
    	//可以把这些线程放到一个数组当中,来进行统一管理
        for (int i = 0; i < maxConnections; i++) {
            PooledConnectionHandler currentHandler = new PooledConnectionHandler();
            new Thread(currentHandler, "Handler " + i).start();
        }
    }



}
 

连接池处理器:

package com.socket.poolSocketServer;

import java.io.*;
import java.net.*;
import java.util.*;

public class PooledConnectionHandler implements Runnable {
    protected Socket connection;
    //静态变量,即所有对象共享该变量
    //以该类为目标创建的线程,将共同等待这个连接池,
    //一旦该连接池中有对象,则通知等待的线程
    protected static List pool = new LinkedList();
    public PooledConnectionHandler() {
    }
    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("Could not find requested file on the server.");
        } catch (IOException e) {
            System.out.println("Error handling a client: " + e);
        }
    }
    //向连接池中添加连接对象,可以在此处控制任务的最大数目(类似超市中待结账的消费者)
    //而等待中的线程类似N多结账的窗口
    public static void processRequest(Socket requestToHandle) {
    	//对共享对象操作时(增加,删除,修改),要考虑到同步
    	//获取互斥锁
        synchronized (pool) {
            pool.add(pool.size(), requestToHandle);
            pool.notifyAll();
        }
    }
    public void run() {
    	//条件可以为一个boolean类型的变量,以便停止线程
        while (true) {
        	//获取互斥锁
            synchronized (pool) {
                while (pool.isEmpty()) {
                    try {
                    	//调用此方法的时候,会放弃对象锁
                        pool.wait();
                    } catch (InterruptedException e) {
                        return;
                    }
                }
                connection = (Socket) pool.remove(0);
            }
            handleConnection();
        }
    }
}

 
分享到:
评论

相关推荐

    delphi多线程socket服务器客户端

    - 在服务器端的OnAccept事件中,创建TThread子类实例,覆盖Execute方法以处理客户端请求。 - 在Execute方法中,可以使用TThread.Synchronize访问UI线程,安全地更新用户界面。 4. 安全通信 - 考虑到网络通信的...

    实战linux socket编程--示例源码.rar_C++ socket_linux 源码_socket 编程 linux_s

    - 为了处理多个客户端连接,服务器端通常会采用多线程或者异步I/O模型。 - 每个客户端连接可以分配一个独立的线程进行处理,避免阻塞其他连接。 7. **实战示例源码分析** - “www.pudn.com.txt”可能是一个文档...

    Java网络编程-多线程,连接池

    Java网络编程是构建分布式应用程序的关键技术,特别是在服务器端开发中,多线程和连接池是其核心概念。本文将深入探讨这两个主题,并结合文件传输的实际应用进行讲解。 首先,我们来理解多线程。在Java中,多线程...

    socket编程之并发服务器连接代码

    在TCP Socket编程中,这通常通过多线程或多进程来实现。服务器端会为每个新连接创建一个新的线程或进程,以便同时处理来自不同客户端的请求。 二、服务器端代码 1. **创建监听Socket**:首先,服务器需要创建一个...

    C++多线程SOCKET收发

    在提供的`server.cpp`中,可能包含了服务器端的实现,它创建一个监听线程,当有新的客户端连接时,创建新的线程处理客户端的请求。`client.cpp`可能是客户端的代码,用于连接服务器并发送/接收数据。`重点.txt`文件...

    C# Socket多线程编程实例

    套接字编程通常包括三个主要步骤:服务器端监听、客户端请求以及连接确认。服务器端首先创建一个监听套接字,开始监听来自客户端的连接请求。一旦有客户端发起请求,服务器端就会接受该请求,并与客户端建立连接。这...

    TCPSOCKET 线程池通信客户端+服务器端示例代码

    在代码中,客户端可能会使用`ThreadPool.QueueUserWorkItem()`方法将处理连接的工作项放入线程池,而服务器端可能在`AcceptTcpClient()`之后立即返回,以便继续监听新的连接请求。为了保证通信的可靠性,可能还会...

    封装的非常完善的socket类,支持服务器客户端多个连接

    Socket编程是计算机网络编程中的重要组成部分,主要用于实现进程间的通信。在给定的标题和描述中,我们可以看到这里提供了一个已经封装得非常完善的Socket类,它支持服务器与客户端的多个连接,大大简化了开发人员的...

    Socket多客户端连接

    3. **并发处理**:为了处理多个客户端,服务器端可能使用线程或异步I/O模型。线程模型中,每个客户端连接创建一个新线程;而在异步I/O模型中,服务器可以同时处理多个连接,而无需为每个连接创建单独的线程。 4. **...

    src_socket_billlxg_服务器_多线程客户端_earow6_源码.zip

    3. **多线程技术**:由于“多线程客户端”一词,我们可以推断服务器端可能采用了多线程模型来处理来自多个客户端的并发连接。每个连接可能被分配到一个独立的线程,以实现并行处理,提高服务效率。线程管理可能涉及...

    JAVA服务器端应用Socket线程池

    本文将通过分析一个具体的Java服务器端应用程序中的Socket线程池实现,探讨线程池的设计思路及其在Socket通信中的应用。 #### 二、Socket线程池的基本概念 Socket通信是网络编程中常用的一种技术,它允许不同...

    Java多线程机制及其在socket编程中的应用.pdf

    2. 服务器端多线程模型:服务器端通常使用多线程模型来处理来自多个客户端的连接。服务器通过accept()方法接受客户端连接后,为每个连接创建一个新线程用于数据的发送和接收。 3. 线程池在socket服务器中的应用:...

    Socket聊天程序(一个服务端,多个客户端)

    在本文中,我们将深入探讨Socket编程的基本概念、C#中的Socket类、服务器端与客户端的设计以及如何实现多用户聊天功能。 首先,Socket是网络通信中的基本组件,它代表了两个网络节点间的一个连接。在C#中,`System...

    C#实现Socket高性能、大容量并发(附完整实例源码)

    - **Server端**:创建ServerSocket,监听指定端口,接收到连接请求后,通过Accept方法创建新的Socket实例处理客户端请求,可能使用多线程或IOCP来处理并发连接。 - **Client端**:创建ClientSocket,与Server建立...

    java socket 多客户端通讯

    本文将深入探讨如何使用Java Socket实现多客户端与服务器的通讯,并涉及多线程技术。 首先,让我们了解Socket的基本结构。在Java中,`java.net.Socket`类代表客户端到服务器的连接,而`java.net.ServerSocket`类...

    TCP实现客户端与服务器端聊天

    如果需要实现多用户聊天,服务器需要维护一个客户端连接池,每个连接对应一个独立的socket,通过非阻塞I/O或多线程/进程处理多个并发连接。 在Linux环境下,可以使用C或C++进行Socket编程,同时,也可以利用如Boost...

    Socket编程 目录连接.doc

    - **服务器端**:创建 `ServerSocket` 对象监听特定端口,并接受客户端的连接请求。为每个客户端创建单独的线程进行管理。 - **客户端**:创建 `Socket` 连接到服务器,通过输入输出流发送和接收消息。 **2.2 抓取...

    JavaEE学习[JavaSE-07Socket编程.rar]

    5. **多线程处理**:如果服务器需要同时处理多个客户端的连接,通常会在接收到新连接时创建新的线程来处理,这样可以让服务器同时处理多个并发连接。 6. **实例化文件名分析**:压缩包中的文件名称可能代表了不同的...

    android客户端加服务端的socket长连接

    综上所述,Android客户端与服务端的Socket长连接涉及到网络编程基础、多线程、数据编码解码、心跳机制、异常处理等多个方面,实现过程中需考虑性能优化和稳定性。通过实践和调试,可以构建出高效可靠的长连接通信...

    TcpTest c# 客户端服务器端 网络编程例程

    本示例"TcpTest c# 客户端服务器端 网络编程例程"提供了一个全面的教程,旨在帮助开发者学习如何在C#环境中实现基于TCP/IP的客户端和服务器端通信。下面我们将深入探讨相关的知识点。 首先,TCP(Transmission ...

Global site tag (gtag.js) - Google Analytics