利用Socket进行Java网络编程.docx
- 文档编号:3643086
- 上传时间:2022-11-24
- 格式:DOCX
- 页数:14
- 大小:60.08KB
利用Socket进行Java网络编程.docx
《利用Socket进行Java网络编程.docx》由会员分享,可在线阅读,更多相关《利用Socket进行Java网络编程.docx(14页珍藏版)》请在冰豆网上搜索。
利用Socket进行Java网络编程
利用Socket进行Java网络编程
Socket是网络上运行的两个程序间双向通讯的一端,它既可以接受请求,也可以发送请求,利用它可以较为方便的编写网络上数据的传递。
在Java中,有专门的Socket类来处理用户的请求和响应。
利用Socket类的方法,就可以实现两台计算机之间的通讯。
这里就介绍一下在Java中如何利用Socket进行网络编程。
在Java中Socket可以理解为客户端或者服务器端的一个特殊的对象,这个对象有两个关键的方法,一个是getInputStream方法,另一个是getOutputStream方法。
getInputStream方法可以得到一个输入流,客户端的Socket对象上的getInputStream方法得到的输入流其实就是从服务器端发回的数据流。
GetOutputStream方法得到一个输出流,客户端Socket对象上的getOutputStream方法返回的输出流就是将要发送到服务器端的数据流,(其实是一个缓冲区,暂时存储将要发送过去的数据)。
程序可以对这些数据流根据需要进行进一步的封装。
本文的例子就对这些数据流进行了一定的封装(关于封装可以参考Java中流的实现部分)。
为了更好的说明问题,这里举了一个网上对话的例子,客户端启动以后,服务器会启动一个线程来与客户进行文字交流。
要完成这个工作,需要完成三个部分的工作,以下依次说明:
一、建立服务器类
Java中有一个专门用来建立Socket服务器的类,名叫ServerSocket,可以用服务器需要使用的端口号作为参数来创建服务器对象。
ServerSocketserver=newServerSocket(9998)
这条语句创建了一个服务器对象,这个服务器使用9998号端口。
当一个客户端程序建立一个Socket连接,所连接的端口号为9998时,服务器对象server便响应这个连接,并且server.accept()方法会创建一个Socket对象。
服务器端便可以利用这个Socket对象与客户进行通讯。
Socketincoming=server.accept()
进而得到输入流和输出流,并进行封装
BufferedReaderin=newBufferedReader(new
InputStreamReader(incoming.getInputStream()));
PrintWriterout=newPrintWriter(incoming.getOutputStream(),true);
随后,就可以使用in.readLine()方法得到客户端的输入,也可以使用out.println()方法向客户端发送数据。
从而可以根据程序的需要对客户端的不同请求进行回应。
在所有通讯结束以后应该关闭这两个数据流,关闭的顺序是先关闭输出流,再关闭输入流,即使用
out.close();
in.close();
二、建立客户端代码
相比服务器端,客户端要简单一些,客户端只需用服务器所在机器的ip以及服务器的端口作为参数创建一个Socket对象。
得到这个对象后,就可以用"建立服务器"部分介绍的方法实现数据的输入和输出。
Socketsocket=newSocket("168.160.12.42",9998);
in=newBufferedReader(newInputStreamReader(socket.getInputStream()));
out=newPrintWriter(socket.getOutputStream(),true);
以上的程序代码建立了一个Socket对象,这个对象连接到ip地址为168.160.12.42的主机上、端口为9998的服务器对象。
并且建立了输入流和输出流,分别对应服务器的输出和客户端的写入。
三、建立用户界面
读者可以根据自己的喜好建立自己的用户界面,这不是本文的重点。
经过以上三个步骤,就可以建立一个比较简单的对话程序。
但是,为了使这个程序更加完善,应进行以下几个改进:
一、现在服务器只能服务一个客户,也就是单线程的。
可以将它改进为多线程服务器。
try
{file:
//建立服务器
ServerSocketserver=newServerSocket(9998);
inti=1;
for(;;)
{
Socketincoming=server.accept();
newServerThread(incoming,i).start();
i++;
}
}catch(IOExceptionex){ex.printStackTrace();}
循环检测是否有客户连接到服务器上,如果有,则创建一个线程来服务这个客户,这个线程的名称是ServerThread,这个类扩展了Thread类,它的编写方法与前述的服务器的写法相同。
二、为了可以随时得到对方传送过来的消息,可以在服务器以及客户端各建立一个独立的线程来察看输入流,如果输入流中有输入,则可以即时显示出来。
代码如下:
newThread()
{
publicvoidrun()
{
try
{
while(true)
{
checkInput();
sleep(1000);//每1000毫秒检测一次
}
}catch(InterruptedExceptionex)
{
}catch(IOExceptionex)
{
}
}
}.start();
其中的checkInput()方法为
privatevoidcheckInput()throwsIOException
{
Stringline;
if((line=in.readLine())!
=null)file:
//检测输入流中是否有新的数据
t.setPartner(line);file:
//将数据流中的消息显示出来
}
通过以上改进,程序就可以比较好的运行了。
附:
服务器的实现代码
import.*;
importjava.io.*;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
publicclasstalkServer
{publicstaticvoidmain(String[]args)
{try
{file:
//建立服务器
ServerSocketserver=newServerSocket(9998);
inti=1;
for(;;)
{Socketincoming=server.accept();
newServerThread(incoming,i).start();
i++;
}
}catch(IOExceptionex){
ex.printStackTrace();
}
}
}
classServerThreadextendsThreadimplementsActionListener
{
privateintthreadNum;
privateSocketsocket;
talkServerFrmt;
BufferedReaderin;
PrintWriterout;
privatebooleantalking=true;
publicServerThread(Sockets,intc)
{threadNum=c;
socket=s;
}
publicvoidactionPerformed(ActionEvente)
{Objectsource=e.getSource();
try{
if(source==t.btnSend)
{out.println(t.getTalk());
t.clearTalk();
}else
if(source==t.btnEnd)
{out.println("谈话过程被对方终止");
out.close();
in.close();
talking=false;
}
}catch(IOExceptionex){
}
}
publicvoidrun()
{try{
t=newtalkServerFrm(newInteger(threadNum).toString(),this);
t.setSize(500,500);
t.show();
in=newBufferedReader(new
InputStreamReader(socket.getInputStream()));
out=newPrintWriter(socket.getOutputStream(),true);
}catch(Exceptione){
}
newThread()
{publicvoidrun()
{try{
while(true)
{checkInput();
sleep(1000);
}
}catch(InterruptedExceptionex){
}catch(IOExceptionex){
}
}
}.start();
while(talking)
{}
t.dispose();
}
privatevoidcheckInput()throwsIOException
{Stringline;
if((line=in.readLine())!
=null)
t.setPartner(line);file:
//这是界面类里的方法,
file:
//用来将line的内容输出到用户界面
}
}
浅谈Socket编程及Java实现
Java是一种可用于进行网络编程的语言,它提供了两种功能强大的网络支持机制:
URL访问网络资源的类和用Socket通讯的类,来满足不同的要求。
一是URL用于访问Internet网上资源的应用;另一种是针对client/server(客户端/服务器)模式的应用以及实现某些特殊的协议的应用,它的通讯过程是基于TCP/IP协议中传输层接口socket实现的。
本文想简单的介绍一下Socket编程的Java实现方法。
客户基于服务器之间使用的大部分通讯组件都是基于socket接口来实现的。
Socket是两个程序之间进行双向数据传输的网络通讯端点,有一个地址和一个端口号来标识。
每个服务程序在提供服务时都要在一个端口进行,而想使用该服务的客户机也必须连接该端口。
Socket因为是基于传输层,所以它是比较原始的通讯协议机制。
通过Socket的数据表现形式为字节流信息,因此通讯双方要想完成某项具体的应用则必须按双方约定的方式进行数据的格式化和解释,我们可以看出使用Socket编程比较麻烦,但是它具有更强的灵活性和更广泛的使用领域。
有些朋友会问,客户机/服务器工作的模式到底是什么样的呢?
好,下面我想结合一张图来介绍一下它们的工作模式。
那么Java应用程序是如何实现上述过程的呢?
包中有两个类Socket和ServerSocket,分别用于在客户机和服务器上创建Socket通讯。
让我们先来看看客户段程序编写的流程:
1、首先调用Socket类的构造函数,以服务器的指定的IP地址或指定的主机名和指定的端口号为参数,创建一个Socket流,在创建Socket流的过程中包含了向服务器请求建立通讯连接的过程实现。
2、建立了客户端通讯Socket后。
就可以使用Socket的方法getInputStream()和getOutputStream()来创建输入/输出流。
这样,使用Socket类后,网络输入输出也转化为使用流对象的过程。
3、使用输入输出流对象的相应方法读写字节流数据,因为流连接着通讯所用的Socket,Socket又是和服务器端建立连接的一个端点,因此数据将通过连接从服务器得到或发向服务器。
这时我们就可以对字节流数据按客户端和服务器之间的协议进行处理,完成双方的通讯任务。
4、待通讯任务完毕后,我们用流对象的close()方法来关闭用于网络通讯的输入输出流,在用Socket对象的close()方法来关闭Socket。
下面,我想通过一个简单的例子来进一步介绍一下客户端程序的编写
代码一:
importjava.io.*;
import.*;
publicclassSocketCommunicationClient
{
publicstaticvoidmain(String[]args)
{
try{
SocketclientSocket=newSocket("mice",9000);//创建一个流Socket并与主机mice上的端口9000相连接
OutputStreamoutput=clientSocket.getOutputStream();//向此Socket写入字节的一个输出流
DataInputStreaminput=newDataInputStream(clientSocket.getInputStream());
file:
//创建新的数据输入流以便从指定的输入流中读出数据
intc;
Stringresponse;
while((c=System.in.read())!
=-1)//从屏幕上接受输入的字符串,并且分解成一个个字符
{
output.write((byte)c);
if(c=='\n')//如果字符为回车,则输出字符串缓冲
{
output.flush();
response=input.readLine();
System.out.println("Communication:
"+response);
}
}
output.close();
input.close();
clientSocket.close();
}catch(Exceptione){
System.err.println("Exception:
"+e);
}
}
}
这个程序是一个非常的简单的数据通讯的例子,程序先创建了一个Socket并和主机mice上的端口9000相连接,然后打开输入输出流,接着程序从标准输入接收字符并写入流中,每写满一行(以用户键入回车为标志),就把缓冲区中的字符串送往mice上的服务器端程序进行处理,等待服务器端的应答。
input.readLine()方法调用将导致程序停滞直到收到应答信息,程序将一直重复这个过程,直到用户输入中止符。
最后程序要关闭socket输入输出流,在关闭socket和服务器端的连接。
上面我们看了如何使用Java编写客户端的Socket接口程序,下面我也想简要的谈一谈服务器端的Socket接口程序的Java实现方法,其过程如下所述:
1、首先调用ServerSocket类以某个端口号为参数,创建一个ServerSocket对象,即是服务器端的服务程序在该指定端口监听的Socket。
2、服务器端程序使用ServerSocket对象的accept()方法,接收来自客户机程序的连接请求,此时服务器端将一直保持停滞状态,直到收到客户端发来的连接请求,此时该方法将返回一个新建的Socket类的实例,代表和客户机建立的通讯链路在服务程序内的通讯端点。
如果采用Java的多线程编程方法,可以实现并发服务器,继续监听来自其他客户的连接请求。
3、使用新建的Socket对象创建输入、输出流对象。
4、使用流对象的方法完成和客户端的数据传输,按约定协议识别并处理来自客户端的请求数据,并把处理的结果返回给客户端。
5、客户端工作完毕后,则服务器端程序关闭和客户端通讯的流和通讯的Socket。
6、在服务器程序运行结束之间,应当关闭用来监听的Socket.
下面让我们来看一个服务器端的程序的Java实现:
代码二:
import.*;
importjava.io.*;
publicclassSocketCommunicationServer
{
publicstaticvoidmain(String[]args)
try
{
booleanflag=true;//设置标志位为真
Socketclient=null;//创建Socketclient以接收来自客户端的请求
StringinputLine;
ServerSocketserverSocket=newServerSocket(9000);//以端口9000创建一个服务器Socket
System.out.println("服务器在端口9000上监听");
file:
//也可以使用serverSocket.getLocalPort()来获得端口号
while(flag)
{
client=serverSocket.accept();
file:
//监听并接受与此Socket的连接,该方法会阻塞直到有一个连接产生
DataInputStreaminput=newDataInputStream(newBufferedInputStream(client.getInputStream()));
PrintStreamoutput=newPrintStream(newBufferedOutputStream(client.getOutputStream());
while((inputLine=input.readLine())!
=null)
{
if(inputLine.equals("Stop"))
{
flag=false;
break;
}
output.println(inputLine);
output.flush();
}
output.close();
input.close();
client.close();
)
serverSocket.close();
)catch(IOExceptione){}
)
)
)
以上,我简略的谈了一下Socket编程的机制以及使用Java进行Socket编程的实现方法,希望能对大家有所帮助。
用Java开发网络软件非常方便和强大,Java的这种力量来源于他独有的一套强大的用于网络的API,这些API是一系列的类和接口,均位于包和中。
在这篇文章中我们将介绍套接字(Socket)慨念,同时以实例说明如何使用NetworkAPI操纵套接字,在完成本文后,你就可以编写网络低端通讯软件。
什么是套接字(Socket)?
NetworkAPI是典型的用于基于TCP/IP网络Java程序与其他程序通讯,NetworkAPI依靠Socket进行通讯。
Socket可以看成在两个程序进行通讯连接中的一个端点,一个程序将一段信息写入Socket中,该Socket将这段信息发送给另外一个Socket中,使这段信息能传送到其他程序中。
如图1
我们来分析一下图1,HostA上的程序A将一段信息写入Socket中,Socket的内容被HostA的网络管理软件访问,并将这段信息通过HostA的网络接口卡发送到HostB,HostB的网络接口卡接收到这段信息后,传送给HostB的网络管理软件,网络管理软件将这段信息保存在HostB的Socket中,然后程序B才能在Socket中阅读这段信息。
假设在图1的网络中添加第三个主机HostC,那么HostA怎么知道信息被正确传送到HostB而不是被传送到HostC中了呢?
基于TCP/IP网络中的每一个主机均被赋予了一个唯一的IP地址,IP地址是一个32位的无符号整数,由于没有转变成二进制,因此通常以小数点分隔,如:
198.163.227.6,正如所见IP地址均由四个部分组成,每个部分的范围都是0-255,以表示8位地址。
值得注意的是IP地址都是32位地址,这是IP协议版本4(简称Ipv4)规定的,目前由于IPv4地址已近耗尽,所以IPv6地址正逐渐代替Ipv4地址,Ipv6地址则是128位无符号整数。
假设第二个程序被加入图1的网络的HostB中,那么由HostA传来的信息如何能被正确的传给程序B而不是传给新加入的程序呢?
这是因为每一个基于TCP/IP网络通讯的程序都被赋予了唯一的端口和端口号,端口是一个信息缓冲区,用于保留Socket中的输入/输出信息,端口号是一个16位无符号整数,范围是0-65535,以区别主机上的每一个程序(端口号就像房屋中的房间号),低于256的短口号保留给标准应用程序,比如pop3的端口号就是110,每一个套接字都组合进了IP地址、端口、端口号,这样形成的整体就可以区别每一个套接字t,下面我们就来谈谈两种套接字:
流套接字和自寻址数据套接字。
流套接字(StreamSocket)
无论何时,在两个网络应用程序之间发送和接收信息时都需要建立一个可靠的连接,流套接字依靠TCP协议来保证信息正确到达目的地,实际上,IP包有可能在网络中丢失或者在传送过程中发生错误,任何一种情况发生,作为接受方的TCP将联系发送方TCP重新发送这个IP包。
这就是所谓的在两个流套接字之间建立可靠的连接。
流套接字在C/S程序中扮演一个必需的角色,客户机程序(需要访问某些服务的网络应用程序)创建一个扮演服务器程序的主机的IP地址和服务器程序(为客户端应
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 利用 Socket 进行 Java 网络 编程