IP地址和端口号组成了所谓的Socket,Socket是网络上运行的程序之间双向通信链路的终结点,是TCP和UDP的基础。
Java中对于网络通信的支持主要包含以下四大类:
1.InetAddress:用于标识网络上的硬件资源。说白了就是标识IP等。
2.URL:统一资源定位符,通过URL可以直接读取或写入网络上的数据。
3.Sockets:使用TCP协议实现网络通信的Socket相关的类。
4.Datagram:使用UDP协议,将数据保存在数据报中,通过网络进行通信。
简单的两个DEMO,介绍java中的InetAddress类和URL类。
介绍InetAddress类:
package com.wang;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
publicclassInetAddressTest{
publicstaticvoid main(String[] args)throwsUnknownHostException{
InetAddress localhost =InetAddress.getLocalHost();
System.out.println("localhost:"+ localhost);
InetAddress address =InetAddress.getByName("wangdaye-PC");
System.out.println(address.getHostAddress()+"="+ address.getHostName());
byte[] bytes = address.getAddress();
System.out.println("字节数组:"+Arrays.toString(bytes));
System.out.println(address);
}
}
介绍URL类:
package com.wang;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
/**
* 端口号未指定,默认为80,getPort()函数返回值为-1
* @author wangdaye
*/
publicclassURLTest{
publicstaticvoid main(String[] args)throwsException{
URL testUrl =new URL("http://www.sina.com:80/sb/index.jsp");
// System.out.println(testUrl.getPort());
URL url =new URL(testUrl,"wang");
System.out.println("协议:"+ url.getProtocol());
System.out.println("主机名:"+ url.getHost());
System.out.println("端口:"+ url.getPort());
System.out.println("文件路径:"+ url.getPath());
System.out.println("文件名称:"+ url.getFile());
System.out.println("相对路径:"+ url.getRef());
System.out.println("查询字符串:"+ url.getQuery());
//读取网络资源的内容
URL baidu =new URL("http://www.baidu.com:80/sb/index.jsp");
InputStream inputStream = baidu.openStream();
InputStreamReader reader =newInputStreamReader(inputStream);
BufferedReader br =newBufferedReader(reader);
while(br.ready()){
String sb = br.readLine();
System.out.println(sb);
}
}
}
基于TCP的socket通信的Demo:
服务端:
package com.wangdaye.socketIO;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 基于TCP通信的socket服务器端
* @author wangdaye
*
*/
publicclassTCPServer{
publicstaticvoid main(String[] args){
try{
//1.创建服务器端socket,即serverSocket,指定绑定端口,并监听此端口。
ServerSocket serverSocket =newServerSocket(8888);
System.out.println("*************服务器即将启动,等待客户端链接*******************");
//2.调用accept()方法开始监听,等待客户端连接,此时处于阻塞状态。
Socket socket = serverSocket.accept();
//3.获取输入流,读取客户端信息
InputStream inputStream = socket.getInputStream();
InputStreamReader reader =newInputStreamReader(inputStream);
BufferedReader br =newBufferedReader(reader);
String sb =null;
while((sb = br.readLine())!=null){
System.out.println("客户端说:"+ sb);
}
socket.shutdownInput();//关闭输入流
//4.关闭资源
br.close();
reader.close();
inputStream.close();
socket.close();
serverSocket.close();
}catch(IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户端:
package com.wangdaye.socketIO;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 基于TCP通信的socket客户端
* @author wangdaye
*
*/
publicclassTCPClient{
publicstaticvoid main(String[] args){
try{
//1.创建客户端socket,并指定服务器地址和端口
Socket socket =newSocket("localhost",8888);
//2.获取输出流,向服务器端发送信息
OutputStream outputStream = socket.getOutputStream();//字节输出流
PrintWriter pw =newPrintWriter(outputStream);//将输出流打包成打印流
pw.write("用户名:sb,密码:123");
pw.flush();
socket.shutdownOutput();
//3.关闭资源
outputStream.close();
socket.close();
}catch(UnknownHostException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
}
多线程服务端:
package com.wangdaye.socketIO;
import java.net.ServerSocket;
import java.net.Socket;
publicclassTCPThreadServer{
publicstaticvoid main(String[] args)throwsException{
ServerSocket serverSocket =newServerSocket(8888);
System.out.println("***********************服务器启动成功,正在等待客户端连接*********************");
Socket socket =null;
int count =0;
while(true){
socket = serverSocket.accept();
count++;
System.out.println("当前客户端连接数量:"+ count);
System.out.println("当前客户端IP地址是:"+ socket.getInetAddress()+",主机名:"+socket.getInetAddress().getHostAddress()+":"+ socket.getPort());
ServerThread serverThread =newServerThread(socket);
serverThread.run();
}
}
}
基于UDP的Socket通信的Demo:
服务端:
package com.wangdaye.socketIO.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
publicclassServerUdp{
publicstaticvoid main(String[] args)throwsException{
System.out.println("***************服务端已经启动,正在等待客户端发送数据*************");
//接收客户端发送的数据
//1.创建服务器端DatagramSocket,指定端口号
DatagramSocket datagramSocket =newDatagramSocket(8800);
//2.创建数据报,接收客户端发送的数据,指定数据包大小
byte[] b =newbyte[1024];
DatagramPacket datagramPacket =newDatagramPacket(b,b.length);
//3.接收客户端发送的数据
datagramSocket.receive(datagramPacket);//此方法在接收到数据之前会一直阻塞
//4.查看客户端发送的信息,读取数据
String str =newString(b,0, datagramPacket.getLength());
System.out.println("我是服务器,客户端说:"+ str);
//向客户端响应数据
//1.获取客户端地址和端口
InetAddress clientAddress=datagramPacket.getAddress();
int clientPort = datagramPacket.getPort();
String sb ="欢迎你,客户端";
byte[] bytes = sb.getBytes();
//2.创建要向客户端发送的数据
DatagramPacket dp =newDatagramPacket(bytes,bytes.length,clientAddress,clientPort);
//3.响应客户端
datagramSocket.send(dp);
//4.关闭连接
datagramSocket.close();
}
}
客户端:
package com.wangdaye.socketIO.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
publicclassClientUdp{
publicstaticvoid main(String[] args)throwsException{
//向服务器端发送数据
//1.定义服务器的地址、端口号
InetAddress inetAddress =InetAddress.getByName("localhost");
int port =8800;
String msg ="我是客户端,我了个去~";
byte[] bytes = msg.getBytes();
//2.创建数据报,包含发送的消息
DatagramPacket packet =newDatagramPacket(bytes,bytes.length,inetAddress,port);
//3.创建DatagramSocket对象
DatagramSocket socket =newDatagramSocket();
//4.发送数据
socket.send(packet);
//接收服务端响应数据
//1.创建数据包,接收服务端响应数据
byte[] receivedBytes =newbyte[1024];
DatagramPacket dp =newDatagramPacket(receivedBytes,receivedBytes.length);
//2.接收服务器端响应数据
socket.receive(dp);
//3.读取数据
String reply =newString(receivedBytes,0,receivedBytes.length);
System.out.println(reply);
//4.关闭资源
socket.close();
}
}
注意:
1.生产环境下,对线程的优先级做一个控制,否则会效率低下
2.输入输出流的关闭问题,关闭了socket,流也就关闭了
3.传递对象,平时都是以字符串传递的
4.传递文件