本节讲点:
客户端套接字:Socket:Socket的创建和使用方法,以及Socket选项和异常。
服务端套接字:ServerSocket:SeverSocket的创建和使用方法,以及ServerSocket选项
简单的Client/Server对话程序
支持多客户端的Client/Server服务响应程序
在学习JDK的网络编程之前先要了解一下网络基础知识和网络协议。
TCP(传输控制协议)一种基于连接的通信协议。可靠传输
UDP(用户数据包协议)不稳定连接的通信协议
TCP和UDP的端口如下:
Telnet:23
SMTP(简单邮件传输协议):25
HTTP(超文本传输协议):80
POP3:110
IP地址类InetAddress
Socket编程意在建立服务器端IP和客户端IP的网络通信连接,因此IP的寻址是建立连接的基础。InetAddress类是Java的IP地址封装类,表示互联网协议地址。IP地址是IP使用的32位或128位无符号数字,它是低级协议,TCP和UDP协议都是在它的基础上构建的。InetAddress类提供了如下操作:
创建InetAddress对象的方法。
InetAddress类没有构造方法,要创建该类的实例对象,可以通过该类的静态方法获得该对象。
(1)取得本机地址:getLocalHost()
函数定义:public static InetAddress getLocalHost() throws UnkonwnHostException;
示例:
try{
//取得本机地址
InetAddress local = InetAddress.getLocalhost();
System.out.println(local);
}catch(UnkownHostException e){}
(2)根据主机名获取地址:getByName(String host);
(3)根据主机名取得一组地址:getAllByName(String host);
(4)根据IP取得地址:getByAddress(byte[] addr);
IPv4地址中,使用4个字节表示,IPv6中使用6个字节表示
(5)根据主机名和IP取得地址:getByAddress(String host,byte[] addr)
2、取得InetAddress类的属性
获取此IP地址的完全限定域名
String getCanonicalHostName();
返回IP地址字符串
String getHostAddress();
获取此IP地址的主机名
String getHostName();
3、判断地址的版本是IPv4还是IPv6
try{
//取得本机地址
InetAddress local = InetAddress.getLocalHost();
//IPv4 or IPv6
byte[] addr = local.getAddress();
if(addr.length == 4){
System.out.println("IP版本 is IPv4");
int firstByte = addr[0];
if(firstByte < 0){
firstByte += 256;
}
if((firstByte & 0x80) == 0){
System.out.println("IP类别 is A");
}else if((firstByte & 0xC0) == 0){
System.out.println("IP类别 is B");
}else if((firstByte & 0xE0) == 0){
System.out.println("IP类别 is C");
}else if((firstByte & 0xF0) == 0){
System.out.println("IP类别 is D");
}else if((firstByte & 0xF8) == 0){
System.out.println("IP类别 is E");
}
}else if(addr.length == 6){
System.out.pringln("IP 版本 is IPv6");
}
}catch(UnkownHostExcetion e){
e.printStackTrace();
}
4、客户端套接字Socket
套接字(Socket)允许程序把网络连接当成一个流,可以向这个流写字节,也可以从这个流中读取字节。套接字为程序员屏蔽了网络的底层细节。
Socket是网络上运行的两个程序间双向通信的一段,它可以接受请求,也可以发送请求,利用它较为方便地编写网络上数据的传递。
Socket的工作过程如下:
(1)、连接到远程机器
(2)、绑定到端口
(3)、接收从远程机器来的绑定端口的连接
(4)、监听到达的数据
(5)、发送数据
(6)、接收数据
(7)、关闭连接
1、创建套接字对象
建立一个到主机host、端口号为port的套接字,连接到远程主机,方法如下:
public Socket(String host,int port) throws unkownHostException IOException;
示例如下:
try{
Socket socket = new Socket("www.baidu.om",80);
}catch(unkownHostException uex){
}catch(IOException e){
}
建立一个套接字,与前一个不同的是它用InetAddress对象指定套接字,如果出错则抛出IOException
public Socket(InetAddress host,int port) throws IOException;
示例如下:
try{
InetAddress addr = InetAddress.getByName("www.baidu.com");
Socket socket = new Socket(addr,80);
}catch...
5、服务器端套接字ServerSocket
每个服务器套接字运行在服务器上有特定的端口,监听这个端口的TCP连接。当远程客户端的Socket试图与服务器指定端口连接时,服务器被激活,判断客户端的连接,并打开两个主机之间固有的连接。一旦客户端与服务器建立了连接,则两者之间就可以传送数据,而数据时通过这个固有的套接字传递的。
ServerSocket的工作过程如下:
(1)、用ServerSocket()方法在指定端口创建一个新的ServerSocket对象
(2)、ServerSocket对象调用accept()方法在指定端口监听到来的连接。accept()一直处于阻塞状态,知道有客户端试图建立连接,这时accept()方法返回连接客户端与服务器的Socket对象
(3)、调用getInputStream()方法或者getOutputStream()方法,或者两者全调用,建立与客户端交互的输入流或输出流。
(4)、服务器与客户端根据一定的协议交互,知道关闭连接
(5)、服务器、客户端或者两者都关闭连接。
(6)、服务器回到第2步,继续监听下一个连接
1、创建SeverSocket对象
创建绑定到特定端口的服务器套接字
ServerSocket(int port);
try{
SeverSocket server = new ServerSocket(12345);
}catch(IOException e){
}
利用指定的backlog创建服务器套接字,并将其绑定到指定的本地端口。backlog表示传入连接指示(对连接的请求)的最大队列长度,如果队列满时受到连接提示,则拒绝连接。backlog参数必须是大于0的正值,如果传递的值小于或者等于0,则使用默认值。
ServerSocket(int port,int backlog);
try{
SeverSocket server = new ServerSocket(12345,20);
}catch(IOException e){
}
服务器端示例如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author Administrator
* Java socket 服务器端简单示例
*/
public class OneServer {
public static void main(String[] args) {
// 启动服务器端
ServerSocket server = null;
try {
server = new ServerSocket(12345);
System.out.println("服务器启动"+
server.getInetAddress().getHostAddress()+":"+
server.getLocalPort());
while(true){
//监听客户端
Socket socket = server.accept();
System.out.println("客户端连接"+
socket.getInetAddress().getHostAddress()+":"+
socket.getPort());
//输入输出流
BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter os = new PrintWriter(socket.getOutputStream());
//循环处理客户端输入
String line;
while((line = is.readLine()) != null){
System.out.println("收到客户端:"+line);
if(line.equals("bye")){
System.out.println("拜拜,我上天去了");
break;
}else{
//读取键盘输入并回复客户端
os.println(sin.readLine());
os.flush();
}
}
//关闭输入/输出流
is.close();
os.close();
//关闭客户端
socket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
server.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
客户端示例:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class OneClient {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
//连接服务器
Socket socket = new Socket(InetAddress.getLocalHost(),12345);
//输入输出流
BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter os = new PrintWriter(socket.getOutputStream());
//循环读入键盘输入内容
String readLine;
while((readLine = sin.readLine()) != null){
os.println(readLine);
os.flush();
//读取服务器端回复
String responeLine = is.readLine();
System.out.println("服务器端回复:"+responeLine);
}
//关闭输出流
is.close();
os.close();
//关闭客户端
socket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果
转载于:https://blog.51cto.com/aku28907/1775429