Java网络通信编程实例(一)

  1. 实验要求:基于图形界面的局域网点对点打字通信程序

    1. 统一图形界面实现拨号连接;发送;接收
    2. 同一界面下显示发送和连接
    3. 在局域网实测
    4. 中文不能有乱码
    5. 连接超时,断开连接等应有显示提示
  2. 设计思路
    1. 点对点通信应该是一个客户机和一个服务器的通信即客户端和服务器都是单线程
    2. 通信肯定要实现多线程即接收和发送信息,这里按照老师给的基于控制台的局域网点对点打字通信程序稍加改动:客户端和服务器实现Runnable接口。重写的run方法作为接收线程体(不再是发送线程体),发送线程体通过main函数实现即创建一个图形界面后在信息输入框里添加发送Enter键按下事件即可达到发送线程体效果。
    3. 数据输入方式选择Scanner,输出方式选择PrintWriter比较方便操作。为防止中文乱码Scanner在构造时默认系统编码(我的为utf-8), PrintWriter是在PrintWriter(String fileName, String csn)选择这个构造器时才会指定字符编码,所以用PrintWriter(OutputStream out, boolean autoFlush)应该是默认系统编码,再指定自动执行刷新即可完成通信。
    4. 将数据显示在Swing界面上即可完成任务。

  3. 实验总结:

    1. 这个简单的socket编程实现了简单的客户端与服务器一对一的通信,但是该程序是单客户端程序即只能是最先启动的客户端与服务器通信,后面的客户端必须 等待前一个客户端退出才能与服务器通信,将在下一个版本改进程序实现多客户端通信!
    2. java网络编程其实在上一学期里就已经学了,老师也给出了样例程序(基于控制台)但是自己老是不能实现基于图像界面的程序也就是说还还有真正理解java多线程编程和网络编程,主要原因是太过执着于界面的美化想像QQ那样多的功能那样好看的界面,却忽略了最基本最核心的东西,因此在今后的学习中要先抓住重点核心才能真正学到东西。
    3. 在学习过程中老是听到或看网上说Swing过时了,啥啥啥也是过时的,于是产生负面情绪,觉得学校学的都没用,但这也真是大学学习的好处学习最基本最基本的东西,只要把这些基本的东西学懂吃透无论后面要学啥做啥都将是如鱼得水。
    4. 愿自己坚持初心,奋力前行

    Java网络通信编程实例(一)_第1张图片

  4. 实验代码:

package com;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
/**
 * 基于图形界面的局域网点对点打字通信程序
1.	统一图形界面实现拨号连接;发送;接收
2.	同一界面下显示发送和连接
3.	在局域网实测
4.	中文不能有乱码
5.	连接超时,断开连接等应有显示提示

 * @author 唐树成
 *
 */
public class Server22 implements Runnable {
	ServerSocket server; 
	Socket client;
	Scanner in;//文本扫描器输入
	PrintWriter out;//打印字符输出流比较方便
	JFrame frame;//服务器图形界面
	JTextField textField;//信息输入框
	JTextArea messageArea;//信息接收区域

	//主函数入口
	public static void main(String[] args) throws UnknownHostException {
		new Thread(new Server22(6666)).start();
	}

	//初始化窗体
	public Server22(int port) {
		init(port);
	}

	//窗体初始化内容
	public void init(int port) {
		//初始化服务器地址
		try {
			server = new ServerSocket(port);
			server.setSoTimeout(10000); //10秒超时
		} catch (IOException e) {
			e.printStackTrace();
		}

		//初始化窗体和窗体内组件
		textField = new JTextField(50);
		messageArea = new JTextArea(16, 50);
		messageArea.setText("等待客户端10秒连接。。。\n");
		messageArea.setEditable(false);
		frame = new JFrame("服务器");
		frame.getContentPane().add(textField, BorderLayout.SOUTH);
		frame.getContentPane().add(new JScrollPane(messageArea), BorderLayout.CENTER);
		frame.pack();
		frame.setVisible(true);
		
		//添加监听事件
		myEvent();

	}

	//事件监听
	public void myEvent(){
		//发送信息事件
		textField.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode() == KeyEvent.VK_ENTER){
					messageArea.append("服务器:"+textField.getText() + "\n");
					out.println("服务器:"+textField.getText());
					textField.setText("");
				}
			}
		});
		//关闭窗体事件默认退出程序
		frame.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e){
				if(null!=out) {
					out.println("@服务器关闭!");
				}
				System.exit(0);
			}
		});
	}
	
	//重写run方法
	public void run()  {//接收线程体
		try {
			client = server.accept();
			in = new Scanner(client.getInputStream()/*,"utf-8"*/);//默认系统字符集utf-8
			out = new PrintWriter(client.getOutputStream(), true);
			while (in.hasNextLine()) {
				String line = in.nextLine();
				messageArea.append(line + "\n");
			}
			if(null!=in) {
				in.close();
			}
			if(null!=out) {
				out.close();
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			JOptionPane.showMessageDialog(frame,"客户端连接超时!");
			textField.setEditable(false);
		}
	}
}

package com;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
/**
 * 基于图形界面的局域网点对点打字通信程序
1.	统一图形界面实现拨号连接;发送;接收
2.	同一界面下显示发送和连接
3.	在局域网实测
4.	中文不能有乱码
5.	连接超时,断开连接等应有显示提示

 * @author 唐树成
 *
 */
public class Client11 implements Runnable {
	Socket client;
	String serverAddress;//服务器地址
	Scanner in;//文本扫描器输入
	PrintWriter out;//打印字符输出流比较方便
	JFrame frame;//客户端图形界面
	JTextField textField;//信息输入框
	JTextArea messageArea;//信息接收区域

	//主函数入口
	public static void main(String[] args) throws UnknownHostException {
		//服务器地址(这里服务器和客户端在同一电脑上)
		String serverAddress = InetAddress.getLocalHost().getHostAddress();
		new Thread(new Client11(serverAddress)).start();
	}

	//初始化窗体
	public Client11(String serverAddress) {
		init(serverAddress);
	}

	//窗体初始化内容
	public void init(String serverAddress) {
		//初始化服务器地址
		this.serverAddress = serverAddress;

		//初始化窗体和窗体内组件
		textField = new JTextField(50);
		messageArea = new JTextArea(16, 50);
		messageArea.setEditable(false);
		frame = new JFrame("客户端");
		frame.getContentPane().add(textField, BorderLayout.SOUTH);
		frame.getContentPane().add(new JScrollPane(messageArea), BorderLayout.CENTER);
		frame.pack();
		frame.setVisible(true);

		//添加监听事件
		myEvent();

	}

	//事件监听
	public void myEvent(){
		textField.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode() == KeyEvent.VK_ENTER){
					messageArea.append("客户端:"+textField.getText() + "\n");
					out.println("客户端:"+textField.getText());
					textField.setText("");
				}
			}
		});
		//关闭窗体事件默认退出程序
		frame.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e){
				if(null!=out) {
					out.println("客户端断开连接");
				}
				System.exit(0);
			}
		});
	}

	//重写run方法
	public void run()  {//接收线程体
		try {
			client = new Socket(serverAddress, 6666);
			messageArea.setText("连接服务器成功!\n");
			in = new Scanner(client.getInputStream()/*,"utf-8"*/);//默认系统字符集utf-8
			out = new PrintWriter(client.getOutputStream(), true);
			out.println("客户端连接成功!");
			while (in.hasNextLine()) {
				String line = in.nextLine();
				if(line.startsWith("@服务器关闭!")) {
					textField.setEditable(false);
					messageArea.append(line.substring(1) + "\n");
				}else {
					messageArea.append(line + "\n");
				}
				
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			messageArea.append("连接服务器失败!\n");
			textField.setEditable(false);
		}
	}
}

附基于控制台的程序代码:

package ppt;
import java.io.*; 
import java.net.*; 

public class Server1 implements Runnable { 
	ServerSocket server; 
	Socket client; 
	Thread send; 
	BufferedReader br; 
	BufferedOutputStream bos;
	public void ServerStart() { 
		try { 
			server=new ServerSocket(5678); 
			System.out.println ("本机端口号:"+server.getLocalPort());
			server.setSoTimeout(10000*6); //10秒超时
			client=server.accept(); 
			System.out.println("已建立连接!"); 
			br=new BufferedReader(new InputStreamReader(client.getInputStream()));
			bos=new BufferedOutputStream(client.getOutputStream());
			send=new Thread(this);
			send.start();
			//以下为接收 
			String str_in;
			while((str_in=br.readLine())!=null) { 
				System.out.println(str_in); 
				if(str_in.equals("bye")) break;
			} 
			send.interrupt(); //中止发送线程 
			br.close();
			server.close(); 
			bos.close();
			client.close(); 
			System.exit(0);
		}catch(Exception e) { 
			System.out.println(e); 
		}   
	} 
	public static void main(String args[]) { 
		Server1 s=new Server1(); 
		s.ServerStart(); 
	} 
	public void run() {//发送线程体
		try { 
			int ch;
			while((ch=System.in.read())!=-1) {
				bos.write(ch); 
				if(ch=='\n') 
					bos.flush(); 
			} 
		} catch(Exception e) { 
			System.out.println(e);
		}
	}
}
package ppt;
import java.io.*; 
import java.net.*; 
public class Client1 implements Runnable { 
	Socket client; 
	Thread send; 
	BufferedReader br; 
	BufferedOutputStream bos; 
	public void ClientStart() { 
		try { 
			client=new Socket("127.0.0.1",5678);
			System.out.println("已建立连接!"); 
			br=new BufferedReader(new InputStreamReader(client.getInputStream())); 
			bos=new BufferedOutputStream(client.getOutputStream()); 
			send=new Thread(this);
			send.start(); 
			//以下为接收 
			String str_in;
			while((str_in=br.readLine())!=null) { 
				System.out.println(str_in);
				if(str_in.equals("bye")) 
					break; 
			}
			send.interrupt();//中止发送线程 
			br.close(); bos.close();
			client.close(); 
			System.exit(0); 
		} catch(Exception e)  {
			System.out.println(e);
		} 
	} //end of ClientStart
	public static void main(String args[]) {
		Client1 c=new Client1(); 
		c.ClientStart();
	} 
	public void run() {//发送线程体
		try { 
			int ch;
			while((ch=System.in.read())!=-1) { 
				bos.write(ch);
				if(ch=='\n') 
					bos.flush();
			} 
		}catch(Exception e) { 
			System.out.println(e);
		} 
	} //end of run 
}  // end of Client1

Java网络通信编程实例(一)_第2张图片
由此可见该程序只能是单客户端聊天程序。
6. 实验结果:
Java网络通信编程实例(一)_第3张图片
Java网络通信编程实例(一)_第4张图片
Java网络通信编程实例(一)_第5张图片
不启动服务器启动客户端
Java网络通信编程实例(一)_第6张图片
启动服务器不启动客户端
Java网络通信编程实例(一)_第7张图片
正常启动后服务器关闭:
Java网络通信编程实例(一)_第8张图片

你可能感兴趣的:(java网络编程)