⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serverframe.java

📁 java聊天室服务器
💻 JAVA
字号:
package XXRoom;

import java.net.*;
import java.io.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import javax.swing.event.*;
import javax.swing.table.AbstractTableModel;
import java.util.List;
import java.util.ArrayList;
import javax.swing.text.*;


public class ServerFrame extends JFrame implements ActionListener
{	
	JTextField portTCP;//TCP端口
	JTable     table;//连接信息
	JButton    accept;//建立服务器
	JButton    kick;//踢人
	JButton    quit;//关闭服务器
	JCheckBox  autoTCP;//自动指定TCP端口	
	JLabel     portLabel1;
	JCheckBox  autoUDP;//自动指定UDP端口	
	JLabel     portLabel2;
	JTextField portUDP;//UDP端口
	JTextPane  tp;//监视用户言论
	AbstractDocument doc;
	SimpleAttributeSet sacBlue;
	SimpleAttributeSet sacRed;
	SimpleAttributeSet sacBlack;

	JTextField tf;//发送消息
	JButton    send;//
	JScrollPane jsp;
	//右键弹出菜单
	JPopupMenu      menu;
	JMenuItem  menuClear;     

	JPanel     link;
	JPanel     info;
	JPanel     op;

	ServerSocket sSocket;
	DatagramSocket dSocket;
	
	ServerThread sThread;

	public ServerFrame( String s )
	{
	//	super( s );
		this.setUndecorated(true); // 去掉窗口的装饰
        this.getRootPane().setWindowDecorationStyle(JRootPane.NONE);
		
		initCompent();

		addListeners();
		
		autoGetPorts();

		reLocate();
		
	}
	
	private void initCompent() 
	{
		link = new JPanel( new FlowLayout() );
		info = new JPanel( new BorderLayout() );
		op   = new JPanel( new FlowLayout() );

		autoTCP  = new JCheckBox ( "自动指定TCP端口" , true );
		portLabel1 = new JLabel ( "TCP端口" );
		portTCP  = new JTextField( 4 );
		portTCP.setEditable( false );

		autoUDP = new JCheckBox( "自动指定UDP端口", true );
		portLabel2 = new JLabel( "UDP端口" );
		portUDP = new JTextField( 4 );
		portUDP.setEditable( false );
		accept = new JButton( "accept" );

		table = new JTable( new LinkTableModel() );
		tp    = new JTextPane(  );
		tp.setEditable( false );
		

		kick = new JButton( "kick" );
		kick.setEnabled( false );
		quit = new JButton( "quit" );

		menu = new JPopupMenu();
		menuClear = new JMenuItem( "Clear" );
		menu.add( menuClear );

		tf = new JTextField( 30 );
		send = new JButton( "Send" );

		link.add( autoTCP );
		link.add( portLabel1 );
		link.add( portTCP );
		link.add( autoUDP );
		link.add( portLabel2 );
		link.add( portUDP );
		link.add( accept );

		info.add( new JScrollPane( table ) , BorderLayout.CENTER );
		jsp = new JScrollPane( tp );
		jsp.setPreferredSize( new Dimension( 100, 100 ) );
		info.add( jsp , BorderLayout.SOUTH );
				
		op.add( tf );
		op.add( send );
		op.add( kick );
		op.add( quit );			
		
		getContentPane().add( link, BorderLayout.NORTH );
		getContentPane().add( info, BorderLayout.CENTER );
		getContentPane().add( op, BorderLayout.SOUTH );	    

		StyledDocument sd = tp.getStyledDocument();
		if( sd instanceof AbstractDocument ) {
			doc = (AbstractDocument) sd;
		}
		else {
			System.err.println( "Can't cast the document" );
			System.exit( 0 );
		}
		sacBlue = new SimpleAttributeSet();
		StyleConstants.setForeground( sacBlue, Color.blue );
		sacRed = new SimpleAttributeSet();
		StyleConstants.setForeground( sacRed,  Color.red );
		sacBlack = new SimpleAttributeSet();
		StyleConstants.setForeground( sacBlack, Color.black );
	}
	
	private void addListeners()
	{
		//退出按钮
		quit.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent e ) {
				dispose();
				System.exit( 1 );
			}
		});
		//令kick有效或无效
		table.getSelectionModel().addListSelectionListener( new ListSelectionListener() {
			public void valueChanged( ListSelectionEvent e ) {
				if( e.getValueIsAdjusting() )
					return;
				ListSelectionModel lsm = (ListSelectionModel)e.getSource();
				if( lsm.isSelectionEmpty() )
					kick.setEnabled( false );
				else
					kick.setEnabled( true );
			}
		});
		//自动选择端口
		autoTCP.addActionListener( this );
		autoUDP.addActionListener( this );
		//连接
		accept.addActionListener( this );
		//ta右键菜单
		tp.addMouseListener( new MouseAdapter() {
			public void mouseReleased( MouseEvent e ) {				
				if( e.isPopupTrigger() ) {					
					menu.show( e.getComponent(), e.getX(), e.getY() );
				}
			}
		});
		//清屏
		menuClear.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent e ) {
				try
				{
					doc.remove( 0, doc.getLength() );
				}
				catch ( BadLocationException er )
				{
					er.printStackTrace();
				}				
			}
		});
		//踢人
		kick.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent e ) {
				
				ListSelectionModel lsm = table.getSelectionModel();
				int min = lsm.getMinSelectionIndex();
				int max = lsm.getMaxSelectionIndex();
				for( int i = min; i <= max; i ++ ) {
					if( lsm.isSelectedIndex( i ) ) {						
						//删除clients用户,messages添加消息,用户收到后向服务器发送一条quit消息
						synchronized( sThread.messages ) {
							sThread.messages.add( "URFUCKED " + table.getValueAt( i, 1 ) );
						}											
					}
				}
			}
		});

		//发送消息
		tf.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent e ) {
				String s = tf.getText();
				if( s.length() == 0 )
					return;
				else {
					synchronized( sThread.messages ) {
						sThread.messages.add( "SERVER: " + s );
					}				
					appendChatMsg ( "Server:\n" , s + "\n" );
					tf.setText( "" );
				}
			}
		});
		send.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent e ) {
				String s = tf.getText();
				if( s.length() == 0 )
					return;
				else {
					synchronized( sThread.messages ) {
						sThread.messages.add( "SERVER: " + s );
					}				
					appendChatMsg ( "Server:\n" , s + "\n" );
					tf.setText( "" );
				}
			}
		});
	}
	
	public void actionPerformed( ActionEvent e ) 
	{
		if( e.getSource() == autoTCP ) {
			if( autoTCP.isSelected() == false ) {
				portTCP.setEditable( true );
			}
			else {
				portTCP.setEditable( false );
				//指定为原来自动获取的端口
				portTCP.setText( Integer.toString( sSocket.getLocalPort() ) );
			}
		}
		if( e.getSource() == autoUDP ) {
			if( autoUDP.isSelected() == false ) {
				portUDP.setEditable( true );
			}
			else {
				portUDP.setEditable( false );
				//指定为原来自动获取的端口
				portUDP.setText( Integer.toString( dSocket.getLocalPort() ) );
			}
		}
		if( e.getSource() == accept )  {
			try
			{
				int tcp = Integer.parseInt( portTCP.getText() );
				int udp = Integer.parseInt( portUDP.getText() );
				//如果端口号和自动指定的不同,重新申请
				if( tcp != sSocket.getLocalPort() ) {
					try
					{
						sSocket.close();
						sSocket = new ServerSocket( tcp );
					}
					catch ( IOException err )
					{
						JOptionPane.showMessageDialog( this, "TCP端口已被其他程序占用" );
						return;
					}
				}

				if( udp != dSocket.getLocalPort() ) {
					
					dSocket.close();
					try
					{
						dSocket = new DatagramSocket( tcp );
					}
					catch( SocketException errr )
					{
						JOptionPane.showMessageDialog( this, "UDP端口已被其他程序占用" );
						return;
					}										
				}
				//将所有相关控件置为不可用
				autoTCP.setEnabled( false );
				autoUDP.setEnabled( false );
				portTCP.setEditable( false );
				portUDP.setEditable( false );
				accept.setEnabled( false );
				
				//开始服务器线程
				JOptionPane.showMessageDialog( this, "OH YEAH! 端口可用,开始等待联机" );
				sThread = new ServerThread( this );
				sThread.start();
			}
			catch ( NumberFormatException er )
			{
				JOptionPane.showMessageDialog( this, "数字格式不正确" );
			}			
		}
	}

	private void reLocate()
	{
		pack();
		//重新设定窗口位置
		int screenWidth = getToolkit().getScreenSize().width;
		int screenHeight = getToolkit().getScreenSize().height;		
		setLocation( screenWidth/2 - getSize().width/2, screenHeight/2 - getSize().height/2 );		
	}
	//自动获取可用端口
	private void autoGetPorts()
	{
		int i = 1000;
		while( true ) {
			try
			{
				sSocket = new ServerSocket( i );
				portTCP.setText( Integer.toString( i ) );				
				break;
			}
			catch ( IOException e )
			{
				++ i;
			}
		}
		i = 1000;
		while( true ) {
			try
			{
				dSocket = new DatagramSocket( i );
				portUDP.setText( Integer.toString( i ) );
				break;
			}
			catch ( IOException ee )
			{
				++ i;
			}
		}
	}
	
	public void dispose()
	{
		try
		{			
			if( sThread != null ) {
				sThread.stop();
				sThread.dispose();
			}			
			if( sSocket != null ) 
				sSocket.close();
			if( dSocket != null )
				dSocket.close();			
		}
		catch ( IOException e )
		{
			JOptionPane.showMessageDialog( this, "关闭Socket发生异常" );
		}
		
		super.dispose();
	}
	
	public void appendChatMsg ( String s1, String s2 )
	{	
		try
		{
			doc.insertString( doc.getLength(), s1, sacBlue );
			doc.insertString( doc.getLength(), s2, sacBlack);
		}
		catch ( BadLocationException e )
		{
			e.printStackTrace();
		}
		jsp.validate();
		JScrollBar jsb = jsp.getVerticalScrollBar();
		jsb.setValue( jsb.getMaximum() );
	}
	
	public void appendSystemMsg ( String s )
	{
		try
		{
			doc.insertString( doc.getLength(), s, sacRed );
		}
		catch ( BadLocationException e )
		{
			e.printStackTrace();
		}
		jsp.validate();
		JScrollBar jsb = jsp.getVerticalScrollBar();
		jsb.setValue( jsb.getMaximum() );
	}
		
	public void appendPersonalChatMsg ( String from , String to, String s ) 
	{
		try
		{
			doc.insertString( doc.getLength(), from, sacBlue );
			doc.insertString( doc.getLength(), " 悄悄地对 " , sacBlack );
			doc.insertString( doc.getLength(), to , sacBlue );
			doc.insertString( doc.getLength(), " 说:\n" , sacBlack );
			doc.insertString( doc.getLength(), s , sacBlack );
		}
		catch ( BadLocationException e )
		{
			e.printStackTrace();
		}
		jsp.validate();
		JScrollBar jsb = jsp.getVerticalScrollBar();
		jsb.setValue( jsb.getMaximum() );
	}

	public static void main(String[] args) 
	{
	
		ServerFrame sf = new ServerFrame( "服务器端" );
		sf.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );		
		
		try
		{		
			UIManager.setLookAndFeel( "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
			SwingUtilities.updateComponentTreeUI( sf );
			sf.validate();
		}
		catch (Exception e )
		{
			System.out.println( "设置LookAndFeel失败" );
		}
		
		sf.setVisible( true );	
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -