j++)
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的输入输出流对象后,利用流的方法实现数据的传输。
调用public
InputStreamgetInputStream()和publicOutputStreamgetOutputStream()方法,分别得到Socket对象的输入输出流。
具体实现代码如下:
packagenupt.java.socket。
import.*。
importjava.io.*。
importjavax.swing.Timer。
publicclassClientextendsThread{
Socketskt。
//用于客户端的连接
//主机地址
//端口号
InetAddresshost。
intport。
BufferedReadertheInputStream。
PrintStreamtheOutputStream。
Stringreadin。
Facechat。
publicClient(Stringip,intp,Facechat){try{
//获取IP地址
//获取端口号
")。
//新建Socket对象
//缓冲区末尾添加字符串
host=InetAddress.getByName(ip)。
port=p。
this.chat=chat。
}catch(IOExceptione){chat.ta.append(e.toString())。
}
}
publicvoidrun(){
try{
chat.ta.append("准备连线,稍后!
skt=newSocket(host,port)。
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(newFlowLayout())。
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()。
}
privateclassTFListenerimplementsKeyListener{publicvoidkeyPressed(KeyEvente){
if(e.getKeyCode()==KeyEvent.VK_ENTER){/按/Enter输出显示聊天内容ta.append(">"+tftype.getText()+"\n")。
if(iamserver)server.dataout(tftype.getText())。
elseclient.dataout(tftype.getText())。
tftype.setText("")。
}
}
publicvoidkeyTyped(KeyEvente){
}
publicvoidkeyReleased(KeyEvente){
}
}
}
1.程序运行初始化界面如下:
2.输入发送的聊天内容后的测试效果:
通过以上测试分析可知,程序很好地完成了课题的要求,运行结果正确,利用JAVA语言的异常处理机制很好地处理了
各种异常,使得程序的性能变得相对稳定,界面舒适易用,可以满足基本聊天需要!
一、调试过程中的问题
程序的调试相对程序的编码复杂多了,需要很大的精力才能做好。
1.问题的描述
(1)JAVA语言的基本知识已具备,但是Socket网络方面还不是很了解,花了不少工夫。
Socket套接字),用于描述IP地
址和端口,通信链的句柄。
应用程序通常通过它向网络发出或应答请求。
有Socket和ServerSocket两个类,ServerSocket
用于服务器端,Socket是建立网络连接时使用的。
在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实
例,完成会话。
(2)关于IP地址的获取,刚开始不知道通过什么方法解决,后来查书知道JAVA的InetAddress类,可以得到主机地址。
但是我想通过程序自动获取加进来的IP地址,可以调用publicbyte[]getAddress()方法,但是没能成功,相互的连接也不是很顺畅,留待下次解决。
2.程序改进的思考
程序只是实现了简单的收发消息功能,功能比较单一,还有许多改进提升的地方。
(1)增加登录界面,用户通过号码和口令进入系统,对用户身份进行验证增加系统的安全性。
(2)可以考虑保存聊天记录功能,方便用户查看。
(3)界面美化方面比较欠缺,可以更加友好和美观。
二、专业课程设计总结第一周的专业课程设计结束了,这是一个不断学习的过程,给我留下了太多的东西。
课题是基于Socket和多线程的聊天程序,我的第一选择就是JAVA语言,因为不管是在网络应用方面还是在多线程支持方面,JAVA都有很大的便利和优势。
同时,我也体会到了Eclipse7.0开发工具的强大功能。
进一步理解了面向对象的思想。
由于JAVA是面向对象的语言,主要的特征就是封装,写类。
在该课题中,很容易就分成三个类,Server类、Client类和Face类,这样分工明确,几个类可以单独写。
再实例化类对象,完成必要的操作。
其中Server类和Client类都是继承Thread类,Face类继承Frame类,实现代码复用。
每次都会谈到程序调试问题,这是个比较重要的问题,我觉得起初就要用工程的思想,从整体上考虑问题,这样调试起来相对简单。
总之,这要靠不断实践来提高。
类似这样的实践都是不断学习的过程,其中肯定会碰到问题,比如这次的JAVA输入输出流问题,不是容易搞清楚的,就要花时间去学习。
以后这样的情况会很多,我们不可能知道所有,学习新知识的能力就显得特别重要了。
不管是同学、老师还是参考书或是网络,都是我们的帮助源,学习源,感谢老师同学的帮助!
课题采用分组的方式进行,组内互相讨论,使得解决问题更加快捷、高效、全面。
同时也提高了团队协作的能力,但是建议以后组内成员最好分工明确,而不要过多依赖,真正参与进去才能学到东西。