socket经典.docx
《socket经典.docx》由会员分享,可在线阅读,更多相关《socket经典.docx(21页珍藏版)》请在冰豆网上搜索。
socket经典
1Java网络编程重点1
2网络编程的基本概念1
2.1网络基础知识1
2.2网络基本概念2
2.3网络传输协议3
3InetAddress类5
4Java套接字6
学士后笔记整理
Socket
1Java网络编程重点
●网络概念
●通信协议分层思想
●TCP/IP协议
●Java对网络编程的支持
●TCP、UDP通信协议的Java实现
●QQ聊天室模块简介
2网络编程的基本概念
2.1网络基础知识
.2.1.1OSI参考模型
2.2网络基本概念
●IP地址:
⏹IP地址用来标识计算机等网络设备的网络地址,由四个8位的二进制数组成,中间以小数点分隔。
如:
192.168.1.3,192.168.1.9;
⏹
●主机名:
⏹网络地址的助记名,按照域名进行分级管理。
●端口号:
⏹网络通信时同一机器上的不同进程的标识。
(其中0—1023是公认端口号;1024—65535是并没有公共定义的端口号,用户可以自己定义这些端口号的作用)
◆公认端口:
从0到1023,它们紧密绑定(Binding)一些服务。
◆注册端口:
从1024到49151。
它们松散地绑定一些服务。
◆动态/私有端口:
从49152到65535,这些端口是应用程序使用的动态端口,应用程序一般不会主动使用这些端口
2.3网络传输协议
TCP:
✓TCP/IP:
传输控制协议/网际协议。
✓TCP/IP实际上是一组协议,它包括上百个各种功能的协议,如:
远程登录、文件传输和电子邮件等,而TCP协议和IP协议是保证数据完整传输的两个基本的重要协议。
✓通过TCP协议传输,得到的是一个顺序的无差错的数据流。
在发送方和接收方成对的两个socket之间必须建立连接,以便在TCP协议的基础上进行通信,
✓可以将TCP协议传输想象为打电话,两个人如果要通话,首先要建立连接—打电话时的拨号,等待响应后—接听电话后,才能相互传递信息,最后还要断开连接—挂电话。
✓
UDP:
✓UDP:
用户数据报协议,是一种无连接的协议。
✓可以将UDP用户数据报协议想象为写信,写完信并填写好收信人的地址并贴邮票后将信投入邮筒,收信人就可以收到了。
在这里寄信人只需要将信寄出去,而不保证收信人一定可以收到。
✓
TCP和UDP两种协议的比较:
1)传输效率
✓使用UDP协议时,每个数据报中都给出了完整的地址信息,因此无须建立发送方和接收方的连接。
✓对于TCP协议,由于它是一个面向连接的协议,在socket之间进行数据传输之前必然要建立连接,所以在TCP协议中多了一个连接建立的时间。
2)传输大小
✓使用UDP协议传输数据时是有大小限制的,每个被传输的数据报必须限定在64KB之内。
✓而TCP协议没有这方面的限制,一旦连接建立起来,双方的socket就可以按统一的格式传输大量的数据。
3)可靠性
✓UDP协议是一个不可靠的协议,发送方所发送的数据报并不一定以相同次序到达接收方。
✓TCP协议是一个可靠的协议,它确保接收方完全正确地获取发送方所发送的全部数据。
客户机/服务器:
✓服务器(server)就是能够提供共享资源的任何东西。
✓客户(client)是简单的任何有权访问特定服务器的实体。
✓客户和服务器之间的连接就像电灯和电源插头的连接。
房间的电源插座是服务器,电灯是客户。
服务器是永久的资源,在访问过服务器之后,客户可以自由的“拔去插头”。
3InetAddress类
ØJava提供了InetAddress类来封装IP地址和DNS。
InetAddress下还有2个子类:
●Inet4Address
●Inet6Address
Ø它们分别代表InternetProtocolversion4(IPv4)地址和InternetProtocolversion6(IPv6)地址。
ØInetAddress类没有提供构造器,而是提供了如下静态方法来获取InetAddress实例:
•用原始IP地址生成InetAddress对象
publicstaticInetAddressgetByAddress(byte[] addr)throwsUnknownHostException
•获取本机IP地址对应的InetAddress实例:
publicstaticInetAddressgetLocalHost()throwsUnknownHostException
•用主机名生成InetAddress对象:
publicstaticInetAddressgetByName(String host)throwsUnknownHostException
例子:
import.*;
publicclassInetAddressTest{
publicstaticvoidmain(Stringargs[])throwsUnknownHostException{
InetAddressAddress=InetAddress.getLocalHost();
//toString返回主机名/IP地址
System.out.println(Address);
Address=InetAddress.getByName("");
System.out.println(Address);
}
}
ØInetAddress还提供了如下三个方法来获取InetAddress实例对应的IP地址和主机名:
•返回该InetAddress实例对应的IP地址(以字符串形式):
publicStringgetHostAddress()
•获取此IP地址的主机名:
publicStringgetHostName()
例子:
下面的例子演示Java如何根据域名自动到DNS查找IP地址
import.*;
publicclassinetaddress{
publicstaticInetAddressina;
publicstaticvoidmain(String[]args){
try{
ina=InetAddress.getByName("");
System.out.println(ina.getHostAddress());
}catch(Exceptione){
System.out.println(e);
}
}
}
4Java套接字
ØJava的TCP/IP套接字用于在主机和Internet之间建立可靠的、双向的、持续的、点对点的流式连接。
ØJava中有两类TCP套接字。
一种是服务器端的,另一种是客户端的。
⏹ServerSocket类设计成在等待客户建立连接之前不做任何事的“监听器”。
用于服务器端。
如果发现客户机端Socket向服务器发出连接请求,且服务器接受服务请求,则服务器端Socket向客户机端Socket发回“接受”的消息。
这样,两个Socket对象之间的连接就建立了。
⏹Socket类为建立连向服务器套接字以及启动协议交换而设计,可以实现TCP/IP通信的客户端。
在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。
Ø在客户端使用socket类,指定服务器IP和端口号,以便连到服务器上:
Socket(host_IP,prot);
在服务器端使用ServerSocket类,以等待客户端的连接:
ServerSocket(port);
ØSocket类
⏹Socket类实现了客户机端的Socket。
Socket对象可以用来向服务器发出连接请求,并交换数据。
下面是用来生成客户套接字的两个构造函数:
Socket(StringhostName,intport)
创建一个本地主机与给定名称的主机和监听端口的套接字连接,可以引发一个UnknownHostException异常或IOException异常。
Socket(InetAddressipAddress,intport)
用一个预先存在的InetAddress对象和端口创建一个套接字,可以引发IOException异常。
其中address表示IP地址,host表示主机名,port表示端口号
ØSocket构造方法实例:
●publicSocket(InetAddress address,int port)
●例1:
●Sockets1=newSocket(InetAddress.getLocalHost(),4000);
●用于向本地机端口4000发起请求连接;
●例2:
●Sockets1=newSocket(InetAddress.getByName(“ComputerName”), 4000);
●用于向机器名为ComputerName的4000端口发起请求连接;
●publicSocket(String host,int port,InetAddress localAddr,int localPort)throwsIOException
●例:
●Socketsl=newSocket(“10.65.111.101”,4000,InetAddress.getLocalHost()
●,1234);
●用于从本地计算机的端口号为1234,向IP地址为10.65.111.101的主机的4000号端口发起连接的请求;
●publicSocket(InetAddress address,int port,InetAddress localAddr,int localPort)throwsIOException
●例:
●newSocket(InetAddress.getByName(“ComputerName”),4000,
InetAddress.getLocalHost(),1234);
●以本地计算机的1234端口,向机器名为ComputerName的主机的4000号端口发起连接请求;
ØSocket类的常用方法
使用下面的方法,可以在任何时候检查套接字的地址和与之有关的端口信息:
InetAddressgetInetAddress( )
获取Socket对象绑定的远程地址;
InetAddressgetLocalAddress()
获取Socket对象绑定的本地地址;
IntgetPort( )
返回与该Socket对象连接的远程端口。
IntgetLocalPort( )
返回与该Socket连接的本地端口。
一旦Socket对象被创建,同样可以检查它获得访问与之相连的输入和输出流的权力。
InputStreamgetInputStream( )
返回与调用套接字有关的InputStream类。
OutputStreamgetOutputStream( )
返回与调用套接字有关的OutputStream类。
voidclose( )
关闭InputStream和OutputStream。
例子:
import.Socket;
publicclassTest{
publicstaticvoidmain(Stringargs[])throwsException{
//创建Socket并建立连接
Socketsocket=newSocket("",80);
//打印服务器地址
System.out.println("服务器地址:
"+socket.getInetAddress().getHostAddress());
//打印服务器端口号
System.out.println("服务器端口号:
"+socket.getPort());
//打印本地地址
System.out.println("本地地址:
"+socket.getLocalAddress().getHostAddress());
//打印本地端口号
System.out.println("本地端口号:
"+socket.getLocalPort());
}
}
ØServerSocket类
●服务器并不是主动地建立连接,而是被动地监听客户端的连接请求。
服务器由类ServerSocket建立。
●ServerSocket类实现了TCP/IP通信服务器端Socket。
ServerSocket对象监听网络中来自客户机的服务请求,根据请求建立连接。
●Socket中的方法也适于ServerSocket
ØServerSocket构造方法实例:
●在指定端口上建立ServerSocket对象,并进入监听状态:
⏹publicServerSocket(intport)throwsIOException
Ø下面的语句建立了一个服务器端ServerSocket对象,并把它绑定到80端口:
ØServerSocketserverSocket=newServerSocket(80);
⏹如果运行时无法绑定到80端口,以上代码会抛出IOException,一般是由以下原因造成的:
●端口已经被其他服务器进程占用;
● 在某些操作系统中,如果没有以超级用户的身份来运行服务器程序,那么操作系统不允许服务器绑定到1~1023之间的端口。
●如果把参数port设为0,表示由操作系统来为服务器分配一个任意可用的端口。
由操作系统分配的端口也称为匿名端口。
对于多数服务器,会使用明确的端口,而不会使用匿名端口,因为客户程序需要事先知道服务器的端口,才能方便地访问服务器。
例子:
如下所示的RandomPort创建了一个ServerSocket,它使用的就是匿名端口。
多次运行RandomPort程序,可得到不同运行结果:
importjava.io.*;
import.*;
publicclassRandomPort{
publicstaticvoidmain(Stringargs[])throwsIOException{
ServerSocketserverSocket=newServerSocket(0);
System.out.println("监听的端口为:
"+serverSocket.getLocalPort());
}
}
多数服务器会监听固定的端口,这样才便于客户程序访问服务器。
匿名端口一般适用于服务器与客户之间的临时通信,通信结束,就断开连接,并且ServerSocket占用的临时端口也被释放。
ØServerSocket类的常用方法
●accept方法
⏹ServerSocket类对象创建后,开始监听连接。
客户端的连接申请将被存放在监听队列中,可以使用accept()方法取出队列中的连接请求:
⏹publicSocketaccept()throwsIOException
⏹该方法在连接到来前将会一直等待客户端触发通信。
⏹accept()是一个阻塞性方法,所谓阻塞性方法就是说该方法被调用后,将等待客户的请求,直到有一个客户启动并请求连接到相同的端口,然后accept()返回一个对应于客户的socket,Java程序将通过该Socket对象与客户端Socket通信。
⏹例如:
⏹SocketclientSocket=serverSocket.accept();
●获得IO流方法
⏹接下来,服务器从Socket对象中获得输入流和输出流,就能与客户交换数据:
⏹InputStreaminStream=clientSocket.getInputStream();
⏹OutputStreamoutStream=clientSocket.getOutputStream();
⏹如果连接请求队列中没有请求,accept方法将会阻塞服务器线程直到一个连接请求到来。
●关闭ServerSocket
⏹publicvoidclose()throwsIOException
⏹使服务器释放占用的端口,并且断开与所有客户的连接。
当一个服务器程序运行结束时,即使没有执行ServerSocket的close()方法,操作系统也会释放这个服务器占用的端口。
因此,服务器程序并不一定要在结束之前执行ServerSocket的close()方法。
⏹如果希望及时释放服务器的端口,以便让其他程序能占用该端口,则可以显式调用ServerSocket的close()方法。
ØSockset通信过程
⏹无论一个Socket通信程序的功能多么齐全、程序多么复杂,其基本结构都是一样的,都包括以下四个基本步骤:
1)在客户方和服务器方创建Socket/ServerSocket。
2)打开连接到Socket的输入/输出流。
3)利用输入/输出流,按照一定的协议对Socket进行读/写操作。
4)关闭输入/输出流和Socket。
⏹通常,程序员的主要工作是针对所要完成的功能在第3步进行编程,第1、2和4步对所有的通信程序来说几乎都是一样的。
创建一个TCP服务器端程序的步骤:
1).创建一个ServerSocket开始监听
2).使用accept()方法取得新的连接
3).从socket中获得I/O流
4).对I/O流进行读写操作,完成与客户的交互
5).关闭客户端I/O流和socket
6).关闭服务器Socket
创建一个TCP客户端程序的步骤:
1).创建Socket
2).获得I/O流
3).对I/O流进行读写操作
4).关闭I/O流
5).关闭Socket
示例:
演示服务器与客户之间的交互,服务器等待,客户访问,相互通信。
◆服务器端:
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.IOException;
import.ServerSocket;
import.Socket;
publicclassServerSocketData{
publicstaticvoidmain(String[]args){
System.out.println("服务器启动!
");
Filefile=newFile("D:
\\lmydataClient.txt");
ServerSocketssk=null;
SocketclientSocket=null;
try{
//绑定端口和客户端发送的端口一致
ssk=newServerSocket(8881);
//监听
clientSocket=ssk.accept();
//打开流
DataInputStreaminstream=newDataInputStream(clientSocket.getInputStream());
DataOutputStreamoutstream=newDataOutputStream(clientSocket.getOutputStream());
outstream.writeUTF("ready!
!
");
while(true){
//读取客户端发送的信息
StringstrClient=instream.readUTF();
System.out.println("客户端说:
"+strClient);
if("exit".equals(strClient)){
System.out.println("服务结束!
");
break;
}else{
//向客户端发送信息
outstream.writeUTF("从服务器端发来的信息:
你好!
客户端");
}
}
instream.close();
outstream.close();
}catch(IOExceptione){
e.printStackTrace();
}finally{
if(ssk!
=null&&clientSocket!
=null){
try{
ssk.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
if(clientSocket!
=null){
try{
clientSocket.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
}
◆客户端:
importjava.io.BufferedReader;
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.io.InputStreamReader;
import.Socket;
import.UnknownHostException;
/**
*客户端
*使用Datainputstream
*@authorAdministrator
*
*/
publicclassSocketData{
publicstaticvoidmain(String[]args){
System.out.println("客户端已经启动!
");
//创建ip和端口
Socketclient=null;
try{
client=newSocket("127.0.0.1",8881);
//打开流,用来接收服务器端发送过来的信息
DataInputStreaminstream=newDataInputStream(client.getInputStream());
//打开流,向服务器端发送信息
DataOutputStreamoutstream=newDataOutputStream(client.getOutputStream());
whil