要实现通信,要通过一个网络线路连接两台计算机。提供信息的计算机或者程序被称为服务器,请求的信息计算机或者程序被称为客户机。
一对一的通讯实现过程:首先,服务器程序创建一个服务器套接字(ServerSocket),调用accept()方法来等待客户机的请求。然后客户端程序创建一个Socket请求与服务器连接,服务器接收客户机的连接请求,同时要创建一个新的Socket与客户建立连接。
服务端代码:
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ChatServer {
static ServerSocket ss;
static Socket sc;
static DataInputStream din;
static DataOutputStream dout;
JButton button;
public ChatServer() {
JFrame frame=new JFrame("服务器"); //窗口名称
JPanel panel1=new JPanel();
final JTextArea textArea1=new JTextArea(); //消息显示区域
final JTextField textArea2=new JTextField(); //聊天内容输入区域
button=new JButton("发送");
Container c=frame.getContentPane();
frame.setLayout(null);
frame.setSize(400, 250);
frame.setVisible(true);
c.add(panel1);
panel1.add(textArea1);
panel1.add(textArea2);
panel1.add(button);
panel1.setLayout(null);
panel1.setBounds(1, 0, 400, 250);
textArea1.setLayout(null);
textArea1.setBounds(0, 0, 400, 180);
textArea2.setLayout(null);
textArea2.setBounds(0, 185, 300, 20);
button.setLayout(null);
button.setBounds(300, 185, 80, 20); //界面布局
textArea2.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode()==KeyEvent.VK_ENTER){ //按Enter进行发送消息
try {
dout.writeUTF(textArea2.getText()); //向客户端发送所输入的信息
textArea1.append("我:"+textArea2.getText()+"\r\n"); //在消息显示区域显示所发送的消息
textArea2.setText(""); //清空
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
button.addActionListener(new ActionListener() { //按钮触发事件
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
try {
dout.writeUTF(textArea2.getText());
textArea1.append("我:"+textArea2.getText()+"\r\n");
textArea2.setText("");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
try {
ss = new ServerSocket(9999); // 实例化ServerSocket对象
sc=ss.accept(); //等待客户端响应连接
din=new DataInputStream(sc.getInputStream());
dout = new DataOutputStream(sc.getOutputStream());
while(true){
textArea1.append("客户端:"+din.readUTF()+"\r\n"); //显示客户端所发送的信息
textArea2.setText("");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String args[]) {
new ChatServer();
}
}
客户端代码:
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ChatClient {
static Socket sc;
static DataInputStream din;
static DataOutputStream dout;
public static void main(String args[]) {
JFrame frame=new JFrame("客户端"); //窗口名字
JPanel panel1=new JPanel();
final JTextArea textArea1=new JTextArea(); // 消息显示区域
final JTextField textArea2=new JTextField(); //输入聊天内容区域
JButton button=new JButton("发送");
Container c=frame.getContentPane();
frame.setLayout(null);
frame.setSize(400, 250);
frame.setVisible(true);
c.add(panel1);
panel1.add(textArea1);
panel1.add(textArea2);
panel1.add(button);
panel1.setLayout(null);
panel1.setBounds(1, 0, 400, 250);
textArea1.setLayout(null);
textArea1.setBounds(0, 0, 400, 180);
textArea2.setLayout(null);
textArea2.setBounds(0, 185, 300, 20);
button.setLayout(null);
button.setBounds(300, 185, 80, 20); //以上是界面布局
textArea2.addKeyListener(new KeyListener() { //键盘事件
@Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode()==KeyEvent.VK_ENTER){ //按Enter键触发
try {
dout.writeUTF(textArea2.getText()); //将写入的内容传送过去
textArea1.append("我:"+textArea2.getText()+"\r\n"); //在自己的文本域里显示信息内容
textArea2.setText(""); //清空写内容的区域
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
button.addActionListener(new ActionListener() { //按钮事件
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
try {
dout.writeUTF(textArea2.getText());
textArea1.append("我:"+textArea2.getText()+"\r\n");
textArea2.setText("");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
try {
sc=new Socket("127.0.0.1",9999); //在客户端创建Socket对象
din=new DataInputStream(sc.getInputStream()); //接收消息
dout = new DataOutputStream(sc.getOutputStream()); //发送消息
while(true){
textArea1.append("服务端:"+din.readUTF()+"\r\n"); //在消息显示区域追加服务器传送过来的消息
textArea2.setText(""); //清空该区域
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行时要先开服务端,再开客户端,否则会报错。
在学习Socket的时候要先看流的概念,要理解InputStream类和OutputStream类,明白网络通信是如何进行交互信息的,我在流这一块卡了很久,想了很久才明白。
实现的功能是服务端和客户端之间的信息交流,利用发送按钮触发事件传送信息和按Enter传送信息。
具体实现的界面如下:
这只是一个简单的通讯程序,有很多没有考虑周到的地方,大家有想法可以往里面加东西。