theOutputStream.println(data);
}
}
classServerThreadextendsThread{
ServerSocketskt;
SocketClient;
TextAreain;
intport,i;
BufferedReadertheInputStream;
PrintStreamtheOutputStream;
Stringreadin;
Facechat;
//服务端子线程
publicServerThread(Sockets,Facechat,inti){
this.i=++i;
Client=s;
this.chat=chat;
}
publicintgetI(){
returnthis.i;
}
publicSocketgetClient(){
returnthis.Client;
}
publicvoidrun(){
try{
theInputStream=newBufferedReader(newInputStreamReader(Client
.getInputStream()));
theOutputStream=newPrintStream(Client.getOutputStream());
while(true){
readin=theInputStream.readLine();
chat.ta.append(readin+"\n");
}
}catch(SocketExceptione){
chat.ta.append("连线中断!
\n");
//设置组件可用性
chat.clientBtn.setEnabled(true);
chat.serverBtn.setEnabled(true);
chat.tfaddress.setEnabled(true);
chat.tfport.setEnabled(true);
try{
i--;
skt.close();
Client.close();
}catch(IOExceptionerr){
chat.ta.append(err.toString());
}
}catch(IOExceptione){
chat.ta.append(e.toString());
}
}
publicvoiddataout(Stringdata){
theOutputStream.println(data);
}
}
2.客户端
客户端主要是使用Socket类,该类是JAVA实现网络编程重要的基础类,实现程序间双向的面向连接的通信。
调用publicSocket(Stringhost,intport)方法设定IP和端口。
建好连接后,用户通过得到Socket的输入输出流对象后,利用流的方法实现数据的传输。
调用publicInputStreamgetInputStream()和publicOutputStreamgetOutputStream()方法,分别得到Socket对象的输入输出流;
具体实现代码如下:
packagenupt.java.socket;
import.*;
importjava.io.*;
importjavax.swing.Timer;
publicclassClientextendsThread{
Socketskt; //用于客户端的连接
InetAddresshost; //主机地址
intport; //端口号
BufferedReadertheInputStream;
PrintStreamtheOutputStream;
Stringreadin;
Facechat;
publicClient(Stringip,intp,Facechat){
try{
host=InetAddress.getByName(ip); //获取IP地址
port=p; //获取端口号
this.chat=chat;
}catch(IOExceptione){
chat.ta.append(e.toString());
}
}
publicvoidrun(){
try{
chat.ta.append("准备连线,稍后!
");
skt=newSocket(host,port); //新建Socket对象
chat.ta.append("成功\n"); //缓冲区末尾添加字符串
theInputStream=newBufferedReader(newInputStreamReader(skt.getInputStream()));
theOutputStream=newPrintStream(skt.getOutputStream());
while(true){
readin=theInputStream.readLine();
chat.ta.append(readin+"\n");
}
}catch(SocketExceptione){
chat.ta.append("未连上!
\n");
chat.clientBtn.setEnabled(true);
chat.serverBtn.setEnabled(true);
chat.tfaddress.setEnabled(true);
chat.tfport.setEnabled(true);
try{
skt.close();
}catch(IOExceptionerr){
chat.ta.append(err.toString());
}
}catch(IOExceptione){
chat.ta.append(e.toString());
}
}
publicvoiddataout(Stringdata){
theOutputStream.println(data);
}
}
3.用户图形界面
该部分主要是完成界面的初始化,合理布局组件,方便用户交互。
主要是JAVA按钮,文本域,标签,布局管理器的使用。
主要处理了键盘Enter消息接受,下面是实现代码:
packagenupt.java.socket;
importjava.awt.*;
importjava.awt.event.*;
publicclassFaceextendsFrame{
privatestaticfinallongserialVersionUID=1L;
ButtonclientBtn,serverBtn;
TextAreata;
TextFieldtfaddress,tfport,tftype;
Labellbl1,lbl2,lbl3;
intport;
Clientclient;
Serverserver;
booleaniamserver;
staticFacefrm;
publicFace(){
//实例化组件
clientBtn=newButton("客户端");
serverBtn=newButton("服务器");
ta=newTextArea("",10,50,TextArea.SCROLLBARS_BOTH);
lbl1=newLabel("IP地址:
");
tfaddress=newTextField("192.168.1.104",10);
lbl2=newLabel("端口:
");
tfport=newTextField("8080");
lbl3=newLabel("发送内容:
");
tftype=newTextField(40);
tftype.addKeyListener(newTFListener());
ta.setEditable(false);
//向容器中加入以上组件
setLayout(new FlowLayout());
add(lbl1);
add(tfaddress);
add(lbl2);
add(tfport);
add(clientBtn);
add(serverBtn);
add(ta);
add(lbl3);
add(tftype);
//设置格式
setLocation(400,250); //窗口显示再屏幕的位置坐标
setSize(400,300); //设置窗体大小
setTitle("基于Socket和多线程编程的聊天程序");
this.setVisible(true); //设置窗体可见
//事件响应
clientBtn.addActionListener(newActionListener(){
publicvoidactionPerformed(ActionEvente){
port=Integer.parseInt(tfport.getText());
client=newClient(tfaddress.getText(),port,frm);
client.start();
tfaddress.setEnabled(false);
tfport.setEnabled(false);
serverBtn.setEnabled(false);
clientBtn.setEnabled(false);
}
});
serverBtn.addActionListener(newActionListener(){
publicvoidactionPerformed(ActionEvente){
port=Integer.parseInt(tfport.getText());
server=newServer(port,frm);
server.start();
iamserver=true;
tfaddress.setText("成为服务器");
tfaddress.setEnabled(false);
tfport.setEnabled(false);
serverBtn.setEnabled(false);
clientBtn.setEnabled(false);
}
});
addWindowListener(newWindowAdapter(){
publicvoidwindowClosing(WindowEvente){
System.exit(0);
}
});
}
publicstaticvoidmain(String[]args){ //主方法
//TODOAuto-generatedmethodstub
frm=newFace();
}
privateclassTFListeneri