真的是做了特别久。这两周刚刚学的awt和swing,顺便自己翻翻舍友的《java入门到入土》,看了一些TCP相关,于是开始着手做这个聊天工具。
一开始对照书写了一个单向的聊天工具,一个是服务器端一个是客户端。只可以客户端向服务器端发消息
客户端是GUI,服务器端是CUI。
[讲解]
稍微做一波讲解。
有一些名词不明白也没关系。想搞懂就百度。
服务器端和客户端交互分3步骤
第一步:服务器程序创建一个ServerSocket(服务器套接字),调用accept方法等待客户机来连接
第二步:客户端程序创建一个Socket(套接字),请求与服务器建立连接。
第三步:服务器接受客户机的连接请求,同时创建一个新的Socket与客户建立连接。服务器继续等待请求。
[代码]
如果想看懂以下的代码需要的知识:
1.awt和swing(做界面的)
2.异常处理。(try…catch…)
3.I/O输入输出。主要是带缓存的输入输出(BufferedInputStream和BufferedoutputStream)
4.TCP
[小菜]
先给大家上个小菜。
使用InetAddress类的getHostName和getHostAddress方法获得本地主机的本机名,和ip地址。
import java.net.*;
public class Main
{
public static void main(String args[])
{
InetAddress ip;
try {
ip=InetAddress.getLocalHost();
String hostname=ip.getHostName();
String hostip=ip.getHostAddress();
System.out.println("本机名:"+hostname);
System.out.println("本机ip:"+hostip);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
[服务器端]
import java.io.*;
import java.net.*;
public class Main
{
public static void main(String args[])
{
InetAddress ip;
try {
ip=InetAddress.getLocalHost();//本地ip
System.out.println(ip.getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}
MyTcp tcp=new MyTcp();
tcp.getserver();
}
}
class MyTcp
{
private BufferedReader reader;
private ServerSocket server;
private Socket socket;
void getserver()
{
try
{
server=new ServerSocket(8998);
System.out.println("服务器Socket已经创建成功了");
while(true)
{
System.out.println("等待客户机连接");
socket=server.accept();
reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
getClientMessage();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void getClientMessage()
{
try
{
while(true)
{
System.out.println("客户机:"+reader.readLine());
}
}
catch(Exception e)
{
e.printStackTrace();
}
try
{
if(reader!=null)
{
reader.close();
}
if(socket!=null)
{
socket.close();
}
}catch(IOException e)
{
e.printStackTrace();
}
}
}
[客户端]
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.border.BevelBorder;
public class Main
{
public static void main(String args[])
{
MyClien clien=new MyClien("向服务器送数据");
clien.setSize(600, 600);
clien.setVisible(true);
clien.connect();
}
}
class MyClien extends JFrame
{
private PrintWriter writer;
Socket socket;
private JTextArea ta=new JTextArea();
private JTextField tf=new JTextField();
Container cc;
public MyClien(String title)
{
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cc=this.getContentPane();
final JScrollPane scrollPane =new JScrollPane();
scrollPane.setBorder(new BevelBorder(BevelBorder.RAISED));
getContentPane().add(scrollPane, BorderLayout.CENTER);
scrollPane.setViewportView(ta);
cc.add(tf, "South");
tf.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
writer.println(tf.getText());
ta.append(tf.getText()+'\n');
ta.setSelectionEnd(ta.getText().length());
tf.setText("");
}
});
}
void connect()
{
ta.append("尝试连接\n");
try
{
socket=new Socket("192.168.1.102 ",8998);
writer=new PrintWriter(socket.getOutputStream(),true);
ta.append("完成连接\n");
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
**
[双向发送TCP]
**
上面的代码是只可以单向发送的。
故琢磨了一个下午做了一个双向发送的版本。
虽然方法很蠢,但还是做出来了。
将服务端和客户端合在一起同时向对法发送消息。
只需输入对方ip和端口(我把端口定死为8998了)。
但是在JTextArea输出的时候还是有点小bug,就是回车的问题。不过不想改了,好懒。
还有就是建议端口数用1024以上的,不然很容易和其他冲突。
上代码
[代码]
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.*;
import java.net.*;
public class Main
{
static int flag=0;
static int isgetip=0;
static String to_ip;
static String to_socket;
public static void main(String args[])
{
String hostip_num = null;
try {
InetAddress ip=InetAddress.getLocalHost();
hostip_num=ip.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
GetInformation gi=new GetInformation(hostip_num);
gi.display();
MyTcp mf=new MyTcp();
mf.display();
}
public static class GetInformation
{
JFrame jframe;
JTextField jtf1;
JTextField jtf2;
JTextField jtf3;
JLabel jl_ip;
JLabel jl_socket;
JLabel jl_hostip;
JButton jb;
MyListener handle;
GetInformation(String ipnum)
{
jframe=new JFrame();
jtf1=new JTextField();
jtf2=new JTextField();
jb=new JButton("确定");
jl_hostip=new JLabel("本 机 ip:"+ipnum);
jl_ip=new JLabel("ip 地 址:");
jl_socket=new JLabel("端口地址:");
handle =new MyListener();
}
void display()
{
jframe.setLayout(null);
jl_hostip.setBounds(10, 10, 300, 30);
jl_ip.setBounds(10, 50, 100, 30);
jl_socket.setBounds(10, 90, 100, 30);
jtf1.setBounds(75, 50, 150, 30);
jtf2.setBounds(75, 90, 150, 30);
jb.setBounds(75, 125, 70, 30);
jb.addActionListener(handle);
jframe.add(jb);
jframe.add(jl_hostip);
jframe.add(jtf1);
jframe.add(jtf2);
jframe.add(jl_socket);
jframe.add(jl_ip);
jframe.setSize(250, 200);
jframe.setAlwaysOnTop(true);
jframe.setVisible(true);
}
class MyListener implements ActionListener
{
public void actionPerformed(ActionEvent e) {
if(jtf1.getText().trim().equals("")||jtf2.getText().trim().equals(""))
{
JOptionPane.showMessageDialog(null,"请输入ip和端口!");
}
else
{
isgetip=1;
to_ip=jtf1.getText();
to_socket=jtf2.getText();
jframe.dispose();
}
}
}
}
public static class MyTcp
{
private JFrame jframe;
private JTextArea jta;
private JTextField jtf;
private PrintWriter writer;
private BufferedReader reader;
private ServerSocket server;
private Socket socket;
private Socket cliensocket;
MyTcp()
{
jframe=new JFrame();
jta=new JTextArea();
jtf=new JTextField();
}
void display()
{
jframe.setLayout(null);
jta.setBounds(10, 10, 465, 400);
jtf.setBounds(10, 430, 465, 20);
jta.setEditable(false);
jtf.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
if(jtf.getText().trim().equals("link")&&isgetip==1&&flag==0)
{
flag=1;
jta.append("尝试连接\n");
try {
cliensocket=new Socket(to_ip,8998);
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
writer=new PrintWriter(cliensocket.getOutputStream(),true);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
jta.append("完成连接\n");
}
writer.println(jtf.getText());
jta.append('\n'+jtf.getText()+'\n');
jta.setSelectionEnd(jta.getText().length());
jtf.setText("");
}
});
jframe.add(jtf);
jframe.add(jta);
jframe.setSize(500, 500);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setVisible(true);
getserver();
}
void getserver()
{
try {
server=new ServerSocket(8998);
jta.append("服务器Socket已经创建成功了\n");
while(true)
{
jta.append("等待客户机连接\n");
socket=server.accept();
reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
getClientMessage();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void getClientMessage()
{
try
{
while(true)
{
jta.append("客户机:"+reader.readLine());
}
}
catch(Exception e)
{
e.printStackTrace();
}
try
{
if(reader!=null)
{
reader.close();
}
if(socket!=null)
{
socket.close();
}
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
/*
if(flag==0&&isgetip==1)
{
flag=1;
cliensocket=new Socket(to_ip,8998);
writer=new PrintWriter(cliensocket.getOutputStream(),true);
jta.append("完成连接\n");
}*/