现在的位置: 首页 > 综合 > 正文

步步测试完善Java中Socket通信图解法(四) .

2013年12月06日 ⁄ 综合 ⁄ 共 4994字 ⁄ 字号 评论关闭

 

    多线程最终服务器和客户端集成一体【swing程序】
    我们通过窗体形式来实验这个socket通信。

    窗体形式,其实把服务器和客户端集成在一起。因此每个窗体程序既是客户端又是服务器端。
    窗体应用程序思路:运行窗体后,此服务器在后台默默监听,而前端展示给客户的是我们所谓的客户端。若服务器接受到相应的消息,则反应在客户端窗体消息窗口中。
    首先脑海中窗体形式如下:
    
    为CS新手补习点图形化知识:
    Java中使用Awt和Swing类来完成图形化界面。其中Awt是abstract window tookit(抽象窗口工具库),他是最早的gui库。
    那为什么会出现swing类呢?他们两者的关联是什么呢?
    1.Awt在所有平台上展示的界面很丑陋,功能也有限。
    2.Awt是非常笨拙、非面向对象的编程方式。
    3.Awt是调用底层平台的GUI实现,因此限制了Awt支持的GUI的实现。
   而swing则:
    1.开发的图形界面要不awt优秀。
    2.采用mvc架构设计,使显示数据与数据来源隔离。
    3.是纯java开发,所以在任何平台都展示一样的效果,而不是依赖平台。
    他们之间的关联是:swing是在awt的基础上开发出来,现在很少使用awt组件,大部分使用swing组件。
   
    在AWT组件结构:
     
    容器的继承关系如下:
   
   事件关系如下:
   
   还有就是布局管理器组件了。代码中会有相应的解释。
   而swing组件关系:
   
    分析我们脑海中的窗体,差不多我们都知道布局。
    因为是Tcp协议测试,所以是基于面向链接发送数据。所以在发送之前,首先要连接服务器,若连接上,然后再发送数据。
    客户端与服务器消息交流都是在中间的消息框中展示。
    在这个窗体中,到底如何布局呢?
    这就需要awt的布局管理器。在代码中,我们用的是BorderLayout组件,布局方式是分为东南西北中,若不指定方向,则默认是中间。
       BoderLayout效果如下:
     
  
     在构造器启动服务,服务一直在监听客户端。
     若监听到,则开启接受信息的线程,其中线程类作为此主线程类的内部类。
     代码如下:并且其中有详细的注释:
     
package com.test;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;



public class SocketTcpDemo1 extends JFrame implements ActionListener {

	 //输入的IP标签
	private JLabel ipLable;
	//输入对方的ip地址
	private JTextField sendIp;
	//连接按钮
	private JButton linkBtn;
	//发送的数据框
	private JTextField sendText;
	//显示数据显示框
	private JTextArea showMessage;
	//创建滚动条 主要是创建垂直滚动条
	private JScrollBar verscrollbar;
	//默认端口号
	private int port=30000;
	//发送按钮
	private JButton sendBtn;
	//默认发送的ip
	public String defaultSendIp="127.0.0.1";
	//连接socket
	private Socket socket;

	//构造方法
	public SocketTcpDemo1()
	{
		this.setTitle("测试tcp通信的窗体");
		this.setBounds(200, 200, 500, 500);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setLayout(new BorderLayout());
		
		//定义消息显示数据框
		showMessage=new JTextArea();
		//设置不可以编辑,消息显示的数据框
		showMessage.setEditable(false);
		
		//消息显示数据框不够,需要添加滚动条
		JScrollPane messageScrollPane=new JScrollPane(showMessage);
		verscrollbar=messageScrollPane.createVerticalScrollBar();
		//把滚动面板放在JFrame容器中
		this.add(messageScrollPane, BorderLayout.CENTER);
		
		//设置连接ip的数据框
		JPanel panel=new JPanel(new BorderLayout(5,2));
		//设置发送默认的ip
		sendIp=new JTextField(defaultSendIp);
		panel.add(sendIp,BorderLayout.CENTER);
		//连接按钮
		linkBtn=new JButton("连接");
		panel.add(linkBtn,BorderLayout.EAST);
		//ip标签显示
		ipLable =new JLabel("对方IP:");
		panel.add(ipLable,BorderLayout.WEST);
		//然后把这个panel放在Frame的上方
		this.add(panel,BorderLayout.NORTH);
		
		//设置发送数据框的位置
		JPanel sendDataPanel=new JPanel(new BorderLayout(5,2));
		//发送数据文本框
		sendText=new JTextField();
		sendDataPanel.add(sendText,BorderLayout.CENTER);
		//发送按钮
		sendBtn=new JButton("发送");
		sendDataPanel.add(sendBtn,BorderLayout.EAST);
		//然后把这个panel放在Frame的下方
		this.add(sendDataPanel,BorderLayout.SOUTH);
		
		//可视化
		this.setVisible(true);
		//添加事件源
		linkBtn.addActionListener(this);
		sendBtn.addActionListener(this);
		//启动监听服务方法
		TcpServer();
		
		
	}
	public void actionPerformed(ActionEvent e) {
		
		if(linkBtn==e.getSource())
		{
			//判断是否能连接上
			try {
				socket=new Socket(sendIp.getText().trim(),port);
                JOptionPane.showMessageDialog(this, "连接成功");

			} catch (Exception e1) {
				try {
					JOptionPane.showMessageDialog(this, "连接失败");
					socket.close();
				} catch (IOException e2) {
					// TODO Auto-generated catch block
					e2.printStackTrace();
				}
			}
		}
		else if(sendBtn==e.getSource())
		{
			try {
				PrintStream ps=new PrintStream(socket.getOutputStream());
				ps.println(sendText.getText());
	
				//显示框中显示
				showMessage.append(InetAddress.getLocalHost().getHostAddress()+"说:"+sendText.getText()+"\n");
				

				sendText.setText("");
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
		}
 
	}
	public static void main(String[] args) {
		SocketTcpDemo1 tcpSocket=new SocketTcpDemo1();
		
	}
	
	//服务监听
	private void TcpServer()
	{
		try {
				ServerSocket ss = new ServerSocket(port);
				while(true)
				{
					//此行代码会阻塞,将一直等待别人的连接
					Socket s=ss.accept();
					new Thread(new ServerThread(s)).start();
				}

			 }
             catch (IOException e) 
             {
			   e.printStackTrace();
		                  
             }
      }

 class ServerThread implements Runnable {

		//定义当前线程所处理的socket
		Socket s=null;
		//该线程所处理的socket所对应的输入流
		BufferedReader br=null;
		
		public ServerThread(Socket s)
		{
			try
			{
				this.s=s;
				//初始化socket对应的输入流
				br=new BufferedReader(new InputStreamReader(s.getInputStream()));
			}
			catch(IOException e)
			{
				e.printStackTrace();
			}		
		}
		
		@Override
		public void run()
		{
			try {
				String content = null;
				 while((content = br.readLine()) != null) {
					 //服务器发送的消息
					showMessage.append(sendIp.getText().trim()+"说:" + content + "\n");
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
	}
}

     效果如下:
     测试连接窗体:
    
    
    互相通信窗口:
   
  至此,目录中的总结都已经整理完毕。
 
  整理这部分内容的原因:第一:socket通信,当时元旦两天测试出来,可当时遇到点问题,所以索性把练习之旅记录下来。第二:练习基础中的多线程,多线程这部分,基本上理论都可以讲出来,但是项目中一直没有用到。第三:初次接触图形化界面,因为这方面内容没有涉及到,大部分是在研究web方向,但是就像揭开他的神秘面纱。
   呵呵,基于以上原因,才有了此次总结的想法。最近一直在研究其他的东西,所以博客没有及时贴出来。(*^__^*)嘻嘻
  
    编译打包成jar包,这部分内容暂时不更新博客了。其实,在打包的过程中应用了ant打包。对于ant的应用,我们有时间再更新博客。

抱歉!评论已关闭.