一、获取ip地址和电脑名
public class InetAddressTest {
public static void main(String[] args) throws Exception {
InetAddress address1=InetAddress.getByName(" ");//通过主机名来返回一个ip地址对象,主机名可以是计算机的名字,也可以是计算机的ip地址
System.out.println(address1);
InetAddress address2=InetAddress.getByName("localhost");
System.out.println(address2);
String hostName=address1.getHostName();
System.out.println(hostName);
InetAddress address3=InetAddress.getByName(hostName);
System.out.println(address3);
String hostAddress=address1.getHostAddress();
System.out.println(hostAddress);
}
}
二、UDP协议
UDP是无连接通信协议,在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在就会发送数据,同时接收端在收到数据时,也不会向发送端反馈是否收到数据。
UDP协议消耗资源小,通信效率高,通常用于音频,视频和普通数据的传输,即使偶尔丢失一两个包也不会对接收结果产生太大影响。
在通信过程中需借助DatagramPacket类,用于封装UDP通信中发送或接收的数据,DatagramPacket类可以当作是用来装载数据的集装箱。
案例:
发送方
public class SendPacket {
public static void main(String[] args){
try {
DatagramSocket datagramSocket=new DatagramSocket();
String st="你好JAVA";
byte[] s=st.getBytes();
InetAddress address=InetAddress.getByName("电脑名和ip地址");
DatagramPacket datagramPacket=new DatagramPacket(s,s.length,address,8087);
datagramSocket.send(datagramPacket);
datagramSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
发送方须指定发送端ip地址和端口号
接收方
public class AcceptPacket {
public static void main(String[] args){
try {
//创建接收端Socket对象 指定端口号
DatagramSocket datagramSocket=new DatagramSocket(8087);
byte[] s=new byte[1024];
//接收数据 将数据存放在s数组中
DatagramPacket datagramPacket=new DatagramPacket(s,0,s.length);
datagramSocket.receive(datagramPacket);
int length=datagramPacket.getLength();
byte[] data=datagramPacket.getData();
System.out.println("data:"+new String(data));
System.out.println("length:"+length);
System.out.println("s:"+new String(s));
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行时需注意,要先运行接收端,后运行发送端
三、TCP协议
UDP中只有发送端和接收端,不区分客户端和服务端,计算机之间可以任意地发送数据。
而TCP通信是严格区分客户端和服务端的,在通信时,必须先由客户端去连接服务器端才能实现通信,服务器端不可以主动去连接客户端,并且服务器端需事先启动,等待客户端连接。
在JDK中提供了两个类用于实现TCP程序,一个是ServerSocket类,用于表示服务器端,一个是Socket类,用于表示客户端。
通信时,首先创建代表服务器端的ServerSocket对象,该对象相当于开启一个服务,并等待客户端的连接,然后创建代表客户端的Socket对象向服务器发起连接请求,服务器响应请求,两者建立连接开始通信。
1、 一个客户端与一个服务端通信
案例:
服务器端
public class Service {
ServerSocket serverSocket;
Socket socket;
public Service(){//初始化ServerSocket
try {
serverSocket=new ServerSocket(8087);
System.out.println("等待客户端连接");
socket=serverSocket.accept();//阻塞,等待客户端连接
System.out.println("客户端链接了");
} catch (IOException e) {
e.printStackTrace();
}
}
public void work(){//写服务端要做的事
//客户端用流来发送,服务端就要用流来接收
//通过客户端的socket来获取
try {
FileInputStream fis=(FileInputStream) socket.getInputStream();
InputStreamReader isr=new InputStreamReader(fis);
char[] message=new char[1024];
int length=isr.read(message);
String s=new String(message,0,length);
System.out.println("客户端说:"+s);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
new Service().work();
}
}
客户端
public class Client {
Socket socket;
public Client(){
try {
socket=new Socket("localhost",8087);//第一个参数放IP地址,第二个参数放端口号
} catch (IOException e) {
e.printStackTrace();
}
}
public void work(){//客户端要做的事
String message="你好,服务端";
try {
FileOutputStream fos=(FileOutputStream) socket.getOutputStream();
OutputStreamWriter osw=new OutputStreamWriter(fos);
osw.write(message);
osw.flush();
osw.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
new Client().work();
}
}
要先运行服务端,后运行客户端
案例:实现客户端与服务端多次通信
服务端
public class Service {
ServerSocket serverSocket;
Socket socket;
public Service(){//初始化ServerSocket
try {
serverSocket=new ServerSocket(8087);
System.out.println("等待客户端连接");
socket=serverSocket.accept();//阻塞,等待客户端连接
System.out.println("客户端链接了");
} catch (IOException e) {
e.printStackTrace();
}
}
public void work(){//写服务端要做的事
//客户端用流来发送,服务端就要用流来接收
//通过客户端的socket来获取
FileInputStream fis=null;
InputStreamReader isr=null;
BufferedReader br=null;
try {
fis=(FileInputStream) socket.getInputStream();
isr=new InputStreamReader(fis,"utf-8");
br=new BufferedReader(isr);
while(true){
String message=br.readLine();
System.out.println("客户端说:"+message);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args){
new Service().work();
}
}
客户端
public class Client {
Socket socket;
public Client(){
try {
socket=new Socket("localhost",8087);//第一个参数放IP地址,第二个参数放端口号
} catch (IOException e) {
e.printStackTrace();
}
}
public void work(){//客户端要做的事
FileOutputStream fos=null;
OutputStreamWriter osw=null;
BufferedWriter bw=null;
Scanner sc=new Scanner(System.in);
try {
fos=(FileOutputStream) socket.getOutputStream();
osw=new OutputStreamWriter(fos,"utf-8");
bw=new BufferedWriter(osw);
while(true){
System.out.println("请输入:");
String message=sc.next();
bw.write(message);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args){
new Client().work();
}
}
案例:用户登录
服务端
public class Service {
ServerSocket serverSocket;
Socket socket;
String uName="zhangsan";
String pWord="123456";
public Service(){
try {
serverSocket=new ServerSocket(8087);
socket=serverSocket.accept();
} catch (IOException e) {
e.printStackTrace();
}
}
public void work(){
FileInputStream fis=null;
InputStreamReader isr=null;
FileOutputStream fos=null;
OutputStreamWriter osw=null;
try {
fis=(FileInputStream) socket.getInputStream();
isr=new InputStreamReader(fis);
fos=(FileOutputStream) socket.getOutputStream();
osw=new OutputStreamWriter(fos);
char[] message=new char[1024];
//读取用户名
int len1=isr.read(message);
String userName=new String(message,0,len1);
System.out.println("userName: "+userName);
//读取密码
int len2=isr.read(message);
String password=new String(message,0,len2);
System.out.println("password: "+password);
if(uName.equals(userName)&&pWord.equals(password)){
osw.write("登陆成功");
osw.flush();
}else {
osw.write("用户名或密码错误");
osw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
isr.close();
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args){
new Service().work();
}
}
客户端
public class Client {
Socket socket;
Scanner sc=new Scanner(System.in);
public Client(){
try {
socket=new Socket("localhost",8087);
} catch (IOException e) {
e.printStackTrace();
}
}
public void work(){
FileOutputStream fos=null;
OutputStreamWriter osw=null;
FileInputStream fis=null;
InputStreamReader isr=null;
try {
fos=(FileOutputStream) socket.getOutputStream();
osw=new OutputStreamWriter(fos);
//每次输入都要刷新一下 否则用户名和密码会同时发送出去
System.out.println("请输入用户名:");
String userName=sc.next();
osw.write(userName);
osw.flush();
System.out.println("请输入密码:");
String password=sc.next();
osw.write(password);
osw.flush();
fis=(FileInputStream) socket.getInputStream();
isr=new InputStreamReader(fis);
char[] result=new char[1024];
int len=isr.read(result);
System.out.println(new String(result,0,len));
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args){
new Client().work();
}
}
2、多个客户端与一个服务端通信
上述的案例都只是一个客户端与一个服务端连接,当服务器想再连接其他客户端时就会出现异常,原因就在于服务器端中的accept()方法,在连接了一个客户端后就会停止,要想让服务器连接多个客户端,只需要让这个方法一直执行。
public Service(){//初始化ServerSocket try { serverSocket=new ServerSocket(8087); while(true) {//导致一个服务端只能连接一个客户端的主要原因就在于accept方法, // 我们只需要让他多次运行就可以实现多个客户端与服务端连接 System.out.println("等待客户端连接"); socket = serverSocket.accept();//阻塞,等待客户端连接 System.out.println("客户端链接了"); } } catch (IOException e) { e.printStackTrace(); } }
但这个方法只能保证多个连接,却不能保证多个客户端同时与服务端通信。当一个客户端与服务端进行通信时,从代码中我们可以注意到这个时候是处在死循环的,也就是说我们不能让当前客户端停止通信,我们需要的是实现多个客户端的并发通信,所以我们就需要借助线程来实现这一需求。
案例:简单的聊天室
服务端
public class Service {
ServerSocket serverSocket;
List<Socket> sockets=new ArrayList<>();
public Service(){//初始化ServerSocket
try {
serverSocket=new ServerSocket(8087);
while (true) {
System.out.println("等待客户端连接");
Socket socket = serverSocket.accept();//阻塞,等待客户端连接
System.out.println("客户端链接了");
sockets.add(socket);
Thread thread=new Thread(){
public void run() {
FileInputStream fis=null;
InputStreamReader isr=null;
BufferedReader br=null;
OutputStream os=null;
OutputStreamWriter osw=null;
BufferedWriter bw=null;
try {
fis=(FileInputStream) socket.getInputStream();
isr=new InputStreamReader(fis,"utf-8");
br=new BufferedReader(isr);
while(true){
String message=br.readLine();
System.out.println("客户端说:"+message);
for (Socket s:sockets){
os=s.getOutputStream();
osw=new OutputStreamWriter(os);
bw=new BufferedWriter(osw);
bw.write(message);
bw.newLine();
bw.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
br.close();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
new Service();
}
}
客户端
public class Client {
Socket socket;
public Client(){
try {
socket=new Socket("localhost",8087);//第一个参数放IP地址,第二个参数放端口号
Thread readThread=new Thread(){
public void run(){
FileInputStream fis=null;
InputStreamReader isr=null;
BufferedReader br=null;
try {
fis=(FileInputStream) socket.getInputStream();
isr=new InputStreamReader(fis,"utf-8");
br=new BufferedReader(isr);
while(true){
String message=br.readLine();
System.out.println("其他客户端说:"+message);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
Thread writeThread=new Thread(){
public void run(){
FileOutputStream fos=null;
OutputStreamWriter osw=null;
BufferedWriter bw=null;
Scanner sc=new Scanner(System.in);
try {
fos=(FileOutputStream) socket.getOutputStream();
osw=new OutputStreamWriter(fos,"utf-8");
bw=new BufferedWriter(osw);
while(true){
System.out.println("请输入:");
String message=sc.next();
bw.write(message);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
readThread.start();
writeThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
new Client();
}
}
Java的网络编程基础部分暂时写到这些,还有一些细节性知识,留待以后完善……