`

服务器响应多个Client的Socket请求

阅读更多
上一篇实现了简单的Client/Server模型的Socket程序。但一般情况下Client会有多个,Server就需要响应多个Client的请求,下面的程序通过多线程实现了这个要求。
package test;

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

public class MultiServer {
	public MultiServer() throws IOException {
		ServerSocket ss=new ServerSocket(7777);
		while(true){
			Socket socket=ss.accept();
			new DealMessage(socket).start();
		}
	}
	public static void main(String[] args) {
		try {
			new MultiServer();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

class DealMessage extends Thread {
	private Socket socket;
	private InputStream in;
	private OutputStream out;

	public DealMessage(Socket s) throws IOException {
		this.socket = s;
		this.in = socket.getInputStream();
		this.out = socket.getOutputStream();
	}

	public void run() {
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			System.out.println("you IP is: " + socket.getInetAddress()+":"+socket.getPort());
			System.out.println("you enter is: " + br.readLine());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void finalize() throws IOException {
		if (in != null) {
			in.close();
		}
		if (out != null) {
			out.close();
		}
	}
}
分享到:
评论
11 楼 marshan 2009-08-25  
不要用ArrayList,它不是线程安全的,换成Vector。
10 楼 cjmcn-sh 2009-05-14  
大概就是这样的吧。可以试试。长连接服务器压力太大。
9 楼 cjmcn-sh 2009-05-14  
搞点代码示意一下:
private static final Set UserSet= Collections
            .synchronizedSet(new HashSet());
然后分几种状态:
OnAccept:
  UserSet.add(Socket);
OnClose;
  UserSet.remove(Socket);
OnSend:
  synchronized (UserSet){
  按照UserSet中socket发送
}
OnException:
UserSet.remove(Socket);
8 楼 lucane 2009-05-13  
cjmcn-sh 写道
保存在list中还是可以的,楼主是选择长连接?保存以后还要做什么特殊处理?
会群发消息?

另外list需要做同步处理。

应该算是长连接
想让用户退出的时候断开链接


给在线所有用户发消息
7 楼 cjmcn-sh 2009-05-12  
保存在list中还是可以的,楼主是选择长连接?保存以后还要做什么特殊处理?
会群发消息?

另外list需要做同步处理。
6 楼 lucane 2009-05-12  
vinter 写道
lucane 写道

san_yun 写道异常时候删除,list需要同步处理.
你说的是对的
但程序还是会出点bug
我这个代码list中放的是Thread
我有点觉得这样写是错的
我看到有别人是把Socket放在list中的
这样有区别吗

保存Socket要更好一些,比如要关掉某一个Socket连接,或者身某个Socket写信息,如果你要是保存Thread,然后Thread里面包含Socket的话,你想用什么方式实现?

我开始想的是从list中删除的话
socket这些资源应该会被回收

我也不是狠懂
正在找这方面的例子。。
5 楼 lqql 2009-05-12  
现在不都用NIO吗?
4 楼 vinter 2009-05-12  
lucane 写道

san_yun 写道异常时候删除,list需要同步处理.
你说的是对的
但程序还是会出点bug
我这个代码list中放的是Thread
我有点觉得这样写是错的
我看到有别人是把Socket放在list中的
这样有区别吗

保存Socket要更好一些,比如要关掉某一个Socket连接,或者身某个Socket写信息,如果你要是保存Thread,然后Thread里面包含Socket的话,你想用什么方式实现?
3 楼 lucane 2009-05-11  
san_yun 写道
异常时候删除,list需要同步处理.

你说的是对的
但程序还是会出点bug
我这个代码list中放的是Thread
我有点觉得这样写是错的
我看到有别人是把Socket放在list中的
这样有区别吗
2 楼 san_yun 2009-05-11  
lucane 写道
我在服务器端维护了一个客户端请求的list
当客户端退出时,服务器端将这个请求的客户端删除
在这里遇到了些问题
主要不知道怎么讲list中下线的客户端删除
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ChatServer {

	List<Client> clients = new ArrayList<Client>();

	public static void main(String[] args) {
		new ChatServer().start();
	}

	public void start() {
		boolean started = false;
		ServerSocket ss = null;
		try {
			ss = new ServerSocket(8888);
			started = true;
		} catch (BindException e) {
			System.out.println("端口正在被使用,请关闭相应程序!");
			System.exit(0);
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			while (started) {
				Socket s = ss.accept();
				Client c = new Client(s);
				clients.add(c);
				System.out.println("a client connected!");
				new Thread(c).start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				ss.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 每个请求过来启用一个线程来处理<br>
	 */
	private class Client implements Runnable {
		Socket socket = null;
		DataInputStream dis = null;
		DataOutputStream dos = null;
		boolean connected = false;

		Client(Socket s) {
			try {
				this.socket = s;
				dis = new DataInputStream(s.getInputStream());
				dos = new DataOutputStream(s.getOutputStream());
				connected = true;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		public void run() {
			while (connected) {
				try {
					Iterator<Client> it = clients.iterator();
					String msg = dis.readUTF();
					while (it.hasNext()) {
						Client c = it.next();
						c.send(msg);
					}

				} catch (EOFException eof) {
					connected = false;
					// 需要在序列中将退出的client去除,
					// 迭代过程中
					// 不能使用Collection本身的remove方法,
					// 会抛出java.util.ConcurrentModificationException
					// 使用iterator的remove方法
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		private void send(String str) throws IOException {
			dos.writeUTF(str);
		}
	}
}


public class ChatClient extends Frame {
	private static final long serialVersionUID = 5798410085795768914L;
	public TextField tf = new TextField();
	public TextArea ta = new TextArea();

	DataOutputStream dos = null;
	DataInputStream dis = null;

	public Socket socket = null;

	boolean connected = false;

	Thread receiver = new Thread(new ReceiverThread());

	public static void main(String[] args) {
		new ChatClient().launchFrame();
	}

	public void launchFrame() {
		this.setLocation(250, 100);
		this.setSize(500, 600);
		this.add(tf, BorderLayout.SOUTH);
		this.add(ta, BorderLayout.NORTH);
		this.pack();
		this.addWindowListener(new WindowMonitor());
		tf.addKeyListener(new KeyMonitor());
		connect();
		receiver.start();
		this.setVisible(true);
	}

	public void connect() {
		try {
			socket = new Socket("127.0.0.1", 8888);
			dos = new DataOutputStream(socket.getOutputStream());
			dis = new DataInputStream(socket.getInputStream());
			connected = true;
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void disconnect() {
		try {
			dos.close();
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private class WindowMonitor extends WindowAdapter {
		@Override
		public void windowClosing(WindowEvent e) {
			disconnect();
			System.exit(0);
		}
	}

	private class KeyMonitor extends KeyAdapter {
		@Override
		public void keyPressed(KeyEvent e) {
			int keyCode = e.getKeyCode();
			if (KeyEvent.VK_ENTER == keyCode) {
				try {
					dos.writeUTF(tf.getText().trim());
					dos.flush();
				} catch (IOException ioe) {
					ioe.printStackTrace();
				}
				tf.setText("");
			}
		}
	}

	private class ReceiverThread implements Runnable {

		public void run() {
			try {
				while (connected) {
					String str = dis.readUTF();
					ta.setText(ta.getText() + str + '\n');
				}
			} catch (SocketException e) {
				System.out.println("客户端断开连接!");
				connected = false;
			} catch (EOFException e) {
				System.out.println("客户端断开连接!");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

异常时候删除,list需要同步处理.
1 楼 lucane 2009-05-11  
我在服务器端维护了一个客户端请求的list
当客户端退出时,服务器端将这个请求的客户端删除
在这里遇到了些问题
主要不知道怎么讲list中下线的客户端删除
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ChatServer {

	List<Client> clients = new ArrayList<Client>();

	public static void main(String[] args) {
		new ChatServer().start();
	}

	public void start() {
		boolean started = false;
		ServerSocket ss = null;
		try {
			ss = new ServerSocket(8888);
			started = true;
		} catch (BindException e) {
			System.out.println("端口正在被使用,请关闭相应程序!");
			System.exit(0);
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			while (started) {
				Socket s = ss.accept();
				Client c = new Client(s);
				clients.add(c);
				System.out.println("a client connected!");
				new Thread(c).start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				ss.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 每个请求过来启用一个线程来处理<br>
	 */
	private class Client implements Runnable {
		Socket socket = null;
		DataInputStream dis = null;
		DataOutputStream dos = null;
		boolean connected = false;

		Client(Socket s) {
			try {
				this.socket = s;
				dis = new DataInputStream(s.getInputStream());
				dos = new DataOutputStream(s.getOutputStream());
				connected = true;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		public void run() {
			while (connected) {
				try {
					Iterator<Client> it = clients.iterator();
					String msg = dis.readUTF();
					while (it.hasNext()) {
						Client c = it.next();
						c.send(msg);
					}

				} catch (EOFException eof) {
					connected = false;
					// 需要在序列中将退出的client去除,
					// 迭代过程中
					// 不能使用Collection本身的remove方法,
					// 会抛出java.util.ConcurrentModificationException
					// 使用iterator的remove方法
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		private void send(String str) throws IOException {
			dos.writeUTF(str);
		}
	}
}


public class ChatClient extends Frame {
	private static final long serialVersionUID = 5798410085795768914L;
	public TextField tf = new TextField();
	public TextArea ta = new TextArea();

	DataOutputStream dos = null;
	DataInputStream dis = null;

	public Socket socket = null;

	boolean connected = false;

	Thread receiver = new Thread(new ReceiverThread());

	public static void main(String[] args) {
		new ChatClient().launchFrame();
	}

	public void launchFrame() {
		this.setLocation(250, 100);
		this.setSize(500, 600);
		this.add(tf, BorderLayout.SOUTH);
		this.add(ta, BorderLayout.NORTH);
		this.pack();
		this.addWindowListener(new WindowMonitor());
		tf.addKeyListener(new KeyMonitor());
		connect();
		receiver.start();
		this.setVisible(true);
	}

	public void connect() {
		try {
			socket = new Socket("127.0.0.1", 8888);
			dos = new DataOutputStream(socket.getOutputStream());
			dis = new DataInputStream(socket.getInputStream());
			connected = true;
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void disconnect() {
		try {
			dos.close();
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private class WindowMonitor extends WindowAdapter {
		@Override
		public void windowClosing(WindowEvent e) {
			disconnect();
			System.exit(0);
		}
	}

	private class KeyMonitor extends KeyAdapter {
		@Override
		public void keyPressed(KeyEvent e) {
			int keyCode = e.getKeyCode();
			if (KeyEvent.VK_ENTER == keyCode) {
				try {
					dos.writeUTF(tf.getText().trim());
					dos.flush();
				} catch (IOException ioe) {
					ioe.printStackTrace();
				}
				tf.setText("");
			}
		}
	}

	private class ReceiverThread implements Runnable {

		public void run() {
			try {
				while (connected) {
					String str = dis.readUTF();
					ta.setText(ta.getText() + str + '\n');
				}
			} catch (SocketException e) {
				System.out.println("客户端断开连接!");
				connected = false;
			} catch (EOFException e) {
				System.out.println("客户端断开连接!");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

相关推荐

    c#多线程socket开发(一个服务器对多个客户端)

    使用C#语言开发多线程Socket服务器端程序可以实现一个服务器同时与多个客户端连接对话,提高了服务器的处理能力和响应速度。同时,该程序也可以实现服务器端的负载均衡和failover机制,以便提高服务器的可用性和可靠...

    socket客户端,可连接多个服务器

    TCP Socket连接的建立遵循三次握手的过程,客户端首先发起连接请求(SYN),服务器响应确认并发送自己的SYN(SYN+ACK),客户端再回应服务器的确认(ACK)。当这三步交互完成,连接便建立成功。而断线后的重连机制,...

    C#使用Socket实现服务器与多个客户端通信(简单的聊天系统)

    在本文中,我们将深入探讨如何使用C#编程语言通过Socket实现一个简单的聊天系统,使得服务器可以与多个客户端进行通信。Socket在计算机网络编程中扮演着重要角色,它提供了进程间通信(IPC)的能力,允许不同计算机...

    c++实现socket:一个服务器对应多个客户端相互传递信息

    描述中的"一个socket对应多个client,每个socket开启一个新的线程"表明服务器会为每个新的客户端连接创建一个新的socket实例,并且在一个单独的线程中运行,这样就可以避免因一个客户端的阻塞操作(如等待输入)而...

    网络编程socket-server-多个client

    本主题将深入探讨“网络编程socket-server-多个client”,重点在于如何处理多个客户端连接,利用Linux操作系统和C语言进行高效的服务器设计。在此过程中,我们将特别关注`select`多路复用技术,以及如何在用户空间中...

    SOCKET 网络编程 计算机网络 作业 客户端 服务器端 client svever

    - **客户端**:发起通信请求的一方,通常负责数据的发送,等待服务器响应。 - **服务器端**:等待并响应客户端请求的一方,通常持续监听特定端口,一旦有连接请求,就创建Socket与客户端建立连接。 4. **Socket...

    C# Socket_服务端向指定的客户端发送消息(包含服务器)

    - 可能还包括多线程或异步处理,以处理多个并发客户端 总的来说,C# Socket编程为我们提供了一种强大的工具来构建网络通信应用。无论是简单的聊天室还是复杂的分布式系统,理解如何创建和管理Socket,以及如何在...

    C#之TcpClient,UdpClient,Socket入门实例

    接收数据则通常通过BeginReceive或ReceiveFrom异步方法实现,因为UDP是多播或广播的,可能会接收到多个源的响应。 最后,我们来看看Socket。Socket是.NET框架中最底层的网络通信接口,它可以用于TCP和UDP协议,甚至...

    使用TCPServer编写(多线程)socket服务

    因为如果只有一个线程处理所有连接,那么当并发连接数量增加时,服务器性能会急剧下降,甚至可能导致服务器响应缓慢或无法处理新的连接。因此,通常我们会使用多线程来为每个连接创建一个独立的工作线程,让每个线程...

    socket server client select模型

    总的来说,"socket server client select模型"是网络编程中的基础实践,通过这种方式,开发者可以构建出能够处理多个并发连接的服务器,从而提升服务的效率和可用性。通过对`server.cpp`和`client.cpp`代码的学习,...

    SocketClient.zip

    在IT行业中,Socket编程是网络通信的基础,它允许两个或多个应用通过TCP/IP协议进行双向通信。下面将详细介绍这些知识点。 1. **Socket编程**:Socket是操作系统提供的一种接口,它允许应用程序通过网络发送和接收...

    HP-Socket开发TCP Client

    在这个"HP-Socket开发TCP Client"的例子中,我们将深入探讨如何使用HP-Socket库来创建一个简单的TCP客户端。 首先,我们需要理解TCP(传输控制协议)的基本概念。TCP是一种面向连接的、可靠的、基于字节流的传输层...

    vc socket实现的聊天室,一个服务器,多个客户端

    在本文中,我们将深入探讨如何使用VC++中的Socket编程实现一个简单的聊天室系统,其中包含一个服务器端和多个客户端。Socket编程是网络通信的核心技术,它允许不同计算机间的进程进行数据交换。在Windows环境中,...

    socketclient.rar

    这种设计使得客户端可以同时接收和处理多个服务器响应,提高了效率。 3. **MainClient.java**:这是整个客户端程序的入口点,负责初始化Socket连接,创建并启动输入和输出线程。在`MainClient.java`中,可能包含了...

    一个server端与多个client端通信python代码

    在Python编程中,实现服务器(Server)与多个客户端(Client)之间的通信是常见的网络编程任务。这个场景通常涉及网络协议,如TCP/IP或UDP,以及多线程或多进程技术来处理来自不同客户端的并发请求。在这个项目中,...

    SocketClient

    SocketClient是一个基于MFC(Microsoft Foundation Classes)框架开发的简单聊天程序,利用了异步套接字技术来实现通信功能。在计算机网络编程中,Socket是应用层与TCP/IP协议族通信的接口,它允许应用程序通过网络...

    Socket服务器与客户端编程(链表)

    通过链表,服务器可以高效地管理多个客户端连接,而Socket则提供了底层的通信机制。改端口可以根据实际需求调整服务器的监听端口,确保服务的正常运行。理解并掌握这部分知识对于进行网络编程和开发分布式应用至关...

    socket-server&client; 初学者版本

    - **并发处理**:如果服务器需要同时处理多个客户端,需要了解多线程或多进程编程。 - **套接字选项**:如设置超时、禁用Nagle算法等,可以优化通信性能。 总之,"socket-server&client; 初学者版本"是一个很好的...

    一个简单的socket程序,包含server和client

    在实际的代码实现中,`Client`和`Server`可能会使用循环来处理多条消息,或者使用多线程或多进程来同时处理多个客户端的请求。为了调试和测试,通常会将服务器和客户端放在同一台机器上运行,但在实际应用中,它们...

    socketDemo

    本示例"socketDemo"旨在展示如何创建一个基本的Socket服务器(socketServer01)来处理多个客户端(socketClient02)的连接,以及客户端之间如何通过服务器进行间接通信。 首先,让我们了解Socket的基本概念。Socket...

Global site tag (gtag.js) - Google Analytics