Java编写TCP网络程序案例

Java编写TCP网络程序案例

要点提示

  1. 服务端,使ServerSocket对象指定监听的端口号,通过Socket对象获得客户端连接
  2. 客户端,使用Socket指定IP地址和端口号
  3. 先运行服务端,再运行客户端,否则会连接失败
  4. 客户端和服务端最好使用一个不断循环的线程监听输入流,以下使用JFrame界面显示效果

服务端程序源码

package io;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.Vector;
/**
 * @author wangzeng
 *
 */
public class TcpServer extends JFrame {
	JTextField txtInput = new JTextField("", 20);
	JButton btnSend = new JButton("发送");
	JList<String> lstMsg = new JList<>();

	public final static int DEFAULT_PORT = 6543;
	protected ServerSocket server = null;
	protected Socket sock = null;
	protected BufferedReader in = null;
	protected PrintWriter out = null;
	DefaultListModel<String> lstMsgModel = new DefaultListModel<>();

	public static void main(String[] args) {
		SwingUtilities.invokeLater(() -> {
			new TcpServer().setVisible(true);
		});
	}

	public TcpServer() {

//		标题
		this.setTitle("服务器");
		
		this.setSize(400, 800);
//		设置居中
		this.setLocationRelativeTo(null);
//		JPanel默认FlowLayout布局
		JPanel southPanel = new JPanel();
		southPanel.add(txtInput);
		southPanel.add(btnSend);
//		Container默认BorderLayout布局
		Container content = this.getContentPane();
		
		content.add(southPanel, BorderLayout.SOUTH);
//		把DefaultList添加到JList组件
		lstMsg.setModel(lstMsgModel);
//		把JList组件加入JScrollPane容器,再把JScrollPane添加到content容器
//		使用new JScrollPane.add(lstMsg)会出现不能显示问题
		content.add(new JScrollPane(lstMsg), BorderLayout.CENTER);
		
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		try {
//			使用ServerSocket创建服务器套接字
			server = new ServerSocket(DEFAULT_PORT);
		} catch (IOException e) {
			System.out.println("server:套接字失败");
//			e.printStackTrace();
		}
//		JButton点击事件:发送信息到客户端
		btnSend.addActionListener((e) -> {
			String str = txtInput.getText();
//			sock可能null
			if(out!=null) {
			out.println(str);
			out.flush();
//			显示到界面
			showMessage(str);
			}
		});
//		监听客户端的线程
		new Thread(() -> {
			try {
//				等待响应
				sock = server.accept();
				System.out.println("server:客户端链接成功");
			} catch (IOException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			}
			while (true) {
				try {
					in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
					out = new PrintWriter(sock.getOutputStream());
					showMessage(in.readLine());
				} catch (IOException e1) {
					// TODO Auto-generated catch block
//					e1.printStackTrace();
					try {
//						accept会阻塞线程,直到有客户端连接才会继续执行
						sock = server.accept();
						System.out.println("server:正在尝试再次连接客户端");
						
					} catch (IOException e2) {
						// TODO Auto-generated catch block
						e2.printStackTrace();
					}
				}
			}
		}).start();

	}
//	显示信息
	public void showMessage(String str) {
		if(str!="") {
		SwingUtilities.invokeLater(() -> {
//			添加到DefaultListModel中
			lstMsgModel.addElement(str);
		});
	}
	}

}

客户端程序源码

package io;

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import javax.swing.*;
import java.net.*;
import java.io.*;

public class TcpClient extends JFrame {

	JTextField txtInput = new JTextField("", 20);
	JButton btnSend = new JButton("发送");

	JList<String> lstMsg = new JList<>();
	DefaultListModel<String> lstMsgModel = new DefaultListModel<>();

	Socket sock;
	BufferedReader in;
	PrintWriter out;
	public final static int DEFAULT_PORT = 6543;

	public static void main(String[] args) {
		SwingUtilities.invokeLater(() -> {
			new TcpClient().setVisible(true);
		});
	}

	public TcpClient() {
		this.setTitle("客户端");
		this.setSize(400, 800);
//		this.setBounds(500, 500, 600, 540);
		Container content = this.getContentPane();
		content.add(new JScrollPane(lstMsg), BorderLayout.CENTER);
		JPanel nothPanel = new JPanel();
		nothPanel.add(txtInput);
		nothPanel.add(btnSend);
		content.add(nothPanel, BorderLayout.SOUTH);
		lstMsg.setModel(lstMsgModel);
	
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		
//		创建套接字
		try {
			sock = new Socket("127.0.0.1", DEFAULT_PORT);
			showMessage("客户端创建套接字成功");
		} catch (IOException e) {
//			e.printStackTrace();
			showMessage("Connection failed");
		}
		
//      发送按钮:向服务器发送信息
		btnSend.addActionListener(e -> {
			if (txtInput.getText().length() != 0) {
				String msg = txtInput.getText();
				out.println(msg);
				out.flush();
				showMessage(msg);
				System.out.println("ChatClient.init():" + txtInput);
			}

		});
		
//		监听服务器消息线程
		new Thread(() -> {
			while (true) {
					try {
						out = new PrintWriter(sock.getOutputStream());
						in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
						String msg = in.readLine();
						showMessage(msg);
					} catch (IOException e1) {
						// TODO Auto-generated catch block
//						e1.printStackTrace();
						System.out.println("Client:服务器出现异常2");
						if(in!=null) {
							try {
								in.close();
							} catch (IOException e2) {
								// TODO Auto-generated catch block
								e2.printStackTrace();
							}
						}
						if(out!=null) {
							out.close();
						}
						try {
							sock.close();
							System.out.println("client:正在关闭");
//							服务端中断后客户端结束while
							break;
						} catch (IOException e2) {
							// TODO Auto-generated catch block
							e2.printStackTrace();
						}
					}
					
					
			}
				
		}).start();

	}
//	显示消息
	public void showMessage(String str) {
		if(str!="") {
		SwingUtilities.invokeLater(() -> {
			lstMsgModel.addElement(str);
		});
		}
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值