Java中的TCP主要涉及ServerSocket和Socket两个类。前者被认为是服务端的一个实体,用于接受连接。后者则被认为是连接的一种封装,用于传输数据,类似于一个管道。
下面我结合Swing写一套客户端和服务端的程序。
程序启动后,客户端程序在窗口的文本框中输入内容。点击发送按钮时向服务器端发送文本框中的文本。服务器端收到信息后。反馈 ok。并在客户端窗口显示。
先看看程序界面:
服务端只有一个文本框,用来接收客户端发送过来的文本信息
客户端,有一个文本框负责输入,一个负责从服务端接收反馈信息,一个发送按钮,点击后就会向服务端发送文本。
下面上代码
客户端:
package swingTCP;
//导入相应的包
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextField;
import javax.swing.JLabel;
import java.awt.Font;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.awt.event.ActionEvent;
@SuppressWarnings("serial")
public class SwingClient extends JFrame {
//界面组件
private JPanel contentPane;
private static JTextField sendText;
private static JTextField textField;
private JLabel returnText;
private static JButton btnSend;
private JLabel textLabel;
//Socket对象
public static Socket socket;
//输出流
public static OutputStream os;
//输入流
public static InputStream is ;
/**
* Launch the application.
*/
public static void main(String[] args) {
//把界面窗口实现出来
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SwingClient frame = new SwingClient();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public SwingClient() {
//设置界面标题
setTitle("\u5BA2\u6237\u7AEF");
try {
//创建Scoket对象,并设置要访问的服务的IP和端口号
//127.0.0.0表示本机地址,也可改为localhost
socket = new Socket("127.0.0.1",987);
//返回此客户端的一个输出流
os = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
sendText = new JTextField();
sendText.setFont(new Font("宋体", Font.PLAIN, 14));
sendText.setBounds(148, 93, 201, 31);
contentPane.add(sendText);
sendText.setColumns(10);
textLabel = new JLabel("\u8F93\u5165\u6587\u672C\uFF1A");
textLabel.setFont(new Font("宋体", Font.PLAIN, 14));
textLabel.setBounds(60, 96, 78, 28);
contentPane.add(textLabel);
btnSend = new JButton("\u53D1\u9001");
btnSend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//从文本框获取要发送的文本
String send = sendText.getText();
try {
//通过流发送信息
os.write(send.getBytes());
//发送一个终结符,告诉服务器,已经发送完毕
socket.shutdownOutput();
//以下是获取服务器回写的数据
//返回此客户端的一个输入流
is = socket.getInputStream();
//将服务器回写的数据进行翻译,并打印在控制台
byte[] bytes = new byte[1024];
int len = 0;
String rs="";
while ((len = is.read(bytes)) != -1) {
rs = rs+new String(bytes,0,len);
//System.out.println(new String(bytes, 0, len));
}
if(rs!=""){
//在文本框显示反馈信息
textField.setText(rs);
}
else{
textField.setText("无返回信息");
}
} catch (IOException e) {
e.printStackTrace();
}finally{
//关闭流资源
try {
if(is!=null){
is.close();
}
if(os!=null){
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
btnSend.setBounds(173, 212, 89, 39);
contentPane.add(btnSend);
textField = new JTextField();
textField.setEditable(false);
textField.setFont(new Font("宋体", Font.PLAIN, 14));
textField.setColumns(10);
textField.setBounds(148, 143, 201, 31);
contentPane.add(textField);
returnText = new JLabel("\u53CD\u9988\u4FE1\u606F");
returnText.setFont(new Font("宋体", Font.PLAIN, 14));
returnText.setBounds(60, 144, 78, 28);
contentPane.add(returnText);
}
}
服务端:
package swingTCP;
//导入相应的包
import java.awt.EventQueue;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextArea;
@SuppressWarnings("serial")
public class SwingServer extends JFrame {
//界面组件
private JPanel contentPane;
static JTextArea textArea = new JTextArea();
//ServerSocket对象
public static ServerSocket ss;
//Socket对象
public static Socket socket;
//输入流
public static InputStream is;
//输出流
public static OutputStream os;
/**
* Launch the application.
*/
public static void main(String[] args) {
/*SwingServer frame = new SwingServer();
frame.setVisible(true);*/
//把界面窗口实现
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SwingServer frame = new SwingServer();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
} catch (Exception e) {
e.printStackTrace();
}
}
});
try {
//创建ServerSocket类,并监听端口987
ss = new ServerSocket(987);
//界面的文本框显示文本
SwingServer.textArea.setText("服务器准备就绪...");
} catch (IOException e) {
e.printStackTrace();
}
while(true){
try {
//获取连接
socket = ss.accept();
//调用Socket的getInputStream()方法,返回服务器输入流
InputStream is = socket.getInputStream();
//信息转成字节数组并输出在控制台
byte[] bytes = new byte[1024];
int len=0;
String getText = "";
while((len = is.read(bytes))!=-1){
getText = getText+new String(bytes,0,len);
//System.out.println(new String(bytes,0,len));
}
//在界面文本框显示收到的信息
SwingServer.textArea.setText(getText);
//服务器返回信息
//调用Socket的getOutputStream()方法,返回服务器输出流
os = socket.getOutputStream();
String rs = "ok";
//通过输出流反馈信息
os.write(rs.getBytes());
//关闭资源
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Create the frame.
*/
public SwingServer() {
setTitle("\u670D\u52A1\u7AEF");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
//textArea = new JTextArea();
textArea.setEditable(false);
textArea.setLineWrap(true);
textArea.setBounds(74, 46, 270, 166);
contentPane.add(textArea);
}
}
运行时要先运行服务端,不然程序会报异常,因为如果先运行客户端的话,没有相应的服务端可以供给客户端连接,就会因为找不到连接端口而报异常。
程序运行,在客户端输入文本,点击发送,即可。