java-网络编程
网络编程
1.网络编程的定义
- 在网络通信协议下,实现网络互联的不同计算机上运行的程序间可以进行数据交换
1.2 网络编程的三要素
- IP地址:计算机的标识符
- 端口:应用程序的标识符
- 协议:计算机之间连接和通信的规则
1.3 IP地址
-
ipv4:32bit地址,一般用10进制点表示法,例如:192.168.1.1
-
ipv6:128bit地址,8组十六进制数组成
1.4 Inet Address类
-
此类表示Internet协议(IP)地址
-
相关方法
| 方法名 | 说明 |
|---|---|
| static inetAddress getByName(String host) | 确定主机名称的ip地址 |
| String getHostName() | 获取此IP地址的主机名 |
| String getHostAddress() | 返回文本显示的IP地址字符串 |
示例
package 网络编程;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Demo {
public static void main(String[] args) throws UnknownHostException {
// 1.根据ip地址创建对象
InetAddress id = InetAddress.getByName("192.168.142.1");
// 2.获取主机名
String hostName = id.getHostName();
System.out.println(hostName);
// 3.返回文本显示的ip字符串
System.out.println(id.getHostAddress());
}
}
- 效果图

1.5 UDP和TCP协议
UDP
- 无连接通信协议,发送端和接收端不产生逻辑链接,发送端不会确认接收端的存在,发送数据报,接收端接收数据也不会有反馈
Tcp
- 传输控制协议
- 三次握手
2. java的UDP通信
-
DategramSocket类
-
构造方法
| 方法名 | 说明 |
|---|---|
| DategramSocket() | 创建数据报文绑定到本地地址的任何可用端口 |
| DategramPacket(byte[] buf,int length,InetAddress address,int port) | 构造一个数据包,发送长度为 length的数据包到指定主机上的指定端口号。 |
- 相关方法
| 方法名 | 说明 |
|---|---|
| void send(DatagramPacket p) | 发送数据报包 |
| void close() | 关闭数据报套接字 |
| void receive(DatagramPacket p) | 接收数据报包 |
发送数据
- 创建DategramSocket对象
- 创建数据,打包(DategramPacket)
- 调用DategramSocket的send方法
- 关闭发送端
package 网络编程;
import java.io.IOException;
import java.net.*;
public class sendDemo {
public static void main(String[] args) throws IOException {
// 1.创建DatagramSocket 对象
DatagramSocket ds = new DatagramSocket();
// 2.创建数据
byte []bys="hello world".getBytes();
// 3.创建DatagramPacket对象
DatagramPacket dp = new DatagramPacket(bys,bys.length, InetAddress.getByName("192.168.142.1"),12345);
// 4.调用send方法
ds.send(dp);
}
}
接收数据
- 构造方法
| 方法名 | 说明 |
|---|---|
| DategramPacket(byte[] buf,int len) | 创建一个DategramPacket用于接收长度为len的数据包 |
- 相关方法
| 方法名 | 说明 |
|---|---|
| byte[] getData() | 返回数据缓冲区 |
| int getLength() | 返回要发送数据的长度或接收数据的长度 |
package 网络编程;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
// 1.创建接收数据包的DatagramSocket对象
DatagramSocket ds = new DatagramSocket(12345);
// 2.创建接收数据包
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
// 3.调用接收方法
ds.receive(dp);
System.out.println(new String(dp.getData(),0,dp.getLength()));
// 4.关闭接收端
ds.close();
}
}
- 效果图

接收和发送数据练习
-
接收端一直接收数据
-
发送端当键盘输入为886时停止发送
-
发送端
package 网络编程.udp通信练习;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class SendDemo {
public static void main(String[] args) throws IOException {
// 1.创建发送Ds
DatagramSocket ds = new DatagramSocket();
// 发送数据来自键盘输入,知道键盘输入为886才停止发送
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
while((str=br.readLine())!=null){
if(str.equals("886")){
break;
}else{
// 3.创建发送数据包
byte[] bys=str.getBytes();
DatagramPacket dp = new DatagramPacket(bys,bys.length, InetAddress.getByName("10.152.242.223"),12345);
ds.send(dp);
}
}
ds.close();
}
}
- 接收端
package 网络编程.udp通信练习;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
// 1.创建接收DatagramSocket
DatagramSocket ds = new DatagramSocket(12345);
// 2.创建接收数据包
while(true){
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
// 3.调用接收方法
ds.receive(dp);
// 4.输出数据
System.out.println(new String(dp.getData(),0,dp.getLength()));
}
}
}
- 效果图

3. java的TCP通信程序
- java为客户端提供了Socket类,为服务器提供了ServerSocket类
3.1 tcp发送数据
- 构造方法
| 方法名 | 说明 |
|---|---|
| Socket(InetAddress address,int port) | 创建流套接字并将其连接到指定IP指定端口号 |
| Socket(String host,int port) | 创建流套接字并将其连接到指定主机的指定端口号 |
- 相关方法
| 方法名 | 说明 |
|---|---|
| InputStream getInputStream() | 返回此套接字的1输入流 |
| OutputStream getOutputStream() | 返回此套接字的输出流 |
3.2 tcp接收数据(服务端)
- 构造方法
| 方法名 | 说明 |
|---|---|
| ServletSocket(int port) | 创建绑定到指定端口的服务器套接字 |
- 相关方法
| 方法名 | 说明 |
|---|---|
| Socket accept() | 监听要连接到此套接字并接收它 |
客户端
package 网络编程.tcp通信;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 1.创建客户端的tcp通信
Socket s = new Socket("10.152.242.223", 12345);
// 2.获取输出流
OutputStream os = s.getOutputStream();
// 3.写数据
os.write("hello.world".getBytes());
s.close();
}
}
服务端
package 网络编程.tcp通信;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 1.服务器端
ServerSocket ss= new ServerSocket(12345);
// 2.获取输入流
// 使用ss.accept()方法连接此套接字并接收
Socket s = ss.accept();
// 获取输入流
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len;
while((len=is.read(bys))!=-1){
String s1 = new String(bys, 0, len);
System.out.println("接收的数据为"+s1);
}
s.close();
ss.close();
}
}
- 效果图

3.3 tcp发送和接收数据(服务器有反馈)
- 客户端
package 网络编程.tcp通信;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 1.创建客户端的tcp通信
Socket s = new Socket("10.152.242.223", 12345);
// 2.获取输出流
OutputStream os = s.getOutputStream();
// 3.写数据
os.write("hello.world".getBytes());
// 客户端接收服务端的反馈
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len;
len=is.read(bys);
System.out.println("服务器的反馈:"+new String(bys,0,len));
s.close();
}
}
- 服务端
package 网络编程.tcp通信;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 1.服务器端
ServerSocket ss= new ServerSocket(12345);
// 2.获取输入流
// 使用ss.accept()方法连接此套接字并接收
Socket s = ss.accept();
// 获取输入流
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len;
len=is.read(bys);
String s1 = new String(bys, 0, len);
System.out.println("接收的数据为"+s1);
//写反馈给客户端
OutputStream os = s.getOutputStream();
os.write("数据已经接收".getBytes());
s.close();
ss.close();
}
}
- 效果图

3.4 tcp发送和接收数据(输入来自键盘输入)
- 客户端
package 网络编程.tcp通信;
import java.io.*;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 1.创建客户端的tcp通信
Socket s = new Socket("10.152.242.223", 12345);
// 2.获取输出流
OutputStream os = s.getOutputStream();
// 3.写数据
//数据来源键盘输入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
//os.write("hello.world".getBytes());
String str;
while((str=br.readLine())!=null){
//如果键盘输入886,停止发送
if(str.equals("886")){
break;
}else{
bw.write(str);
bw.newLine();
bw.flush();
}
}
// 客户端接收服务端的反馈
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len;
len=is.read(bys);
System.out.println("服务器的反馈:"+new String(bys,0,len));
s.close();
}
}
- 服务端
package 网络编程.tcp通信;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 1.服务器端
ServerSocket ss= new ServerSocket(12345);
// 2.获取输入流
// 使用ss.accept()方法连接此套接字并接收
Socket s = ss.accept();
// 获取输入流
InputStream is = s.getInputStream();
//byte[] bys = new byte[1024];
//int len;
//len=is.read(bys);
//String s1 = new String(bys, 0, len);
//System.out.println("接收的数据为"+s1);
//通过字符流读数据
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String str;
while((str=br.readLine())!=null){
System.out.println(str);
}
//写反馈给客户端
OutputStream os = s.getOutputStream();
os.write("数据已经接收".getBytes());
s.close();
ss.close();
}
}
- 效果图

3.5 tcp发送和接收数据(都来自文件)
- 客户端
package 网络编程.tcp通信;
import java.io.*;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 1.创建客户端的tcp通信
Socket s = new Socket("10.152.242.223", 12345);
// 2.获取输出流
OutputStream os = s.getOutputStream();
// 3.写数据
//数据来源键盘输入
//BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
//os.write("hello.world".getBytes());
//数据来源于文件
BufferedReader br = new BufferedReader(new FileReader("code\\13.txt"));
String str;
while((str=br.readLine())!=null){
//如果键盘输入886,停止发送
//if(str.equals("886")){
// break;
//}else{
bw.write(str);
bw.newLine();
bw.flush();
//}
}
// 客户端接收服务端的反馈
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len;
len=is.read(bys);
System.out.println("服务器的反馈:"+new String(bys,0,len));
s.close();
}
}
- 服务端
package 网络编程.tcp通信;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 1.服务器端
ServerSocket ss= new ServerSocket(12345);
// 2.获取输入流
// 使用ss.accept()方法连接此套接字并接收
Socket s = ss.accept();
// 获取输入流
InputStream is = s.getInputStream();
//byte[] bys = new byte[1024];
//int len;
//len=is.read(bys);
//String s1 = new String(bys, 0, len);
//System.out.println("接收的数据为"+s1);
//通过字符流读数据
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String str;
//数据写入文件
BufferedWriter bw = new BufferedWriter(new FileWriter("code\\14.txt"));
while((str=br.readLine())!=null){
//System.out.println(str);
bw.write(str);
bw.newLine();
bw.flush();
}
//写反馈给客户端
OutputStream os = s.getOutputStream();
os.write("数据已经接收".getBytes());
s.close();
ss.close();
}
}
- 效果图

3.6 客户端告知服务端传输完毕的方法
- 相关方法
| 方法名 | 说明 |
|---|---|
| void shutdownInput() | 将此套接字的输入流放置在流的末尾 |
| void shutdownOutput() | 禁止用此套接字的输出流 |
- 客户端
package 网络编程.tcp通信;
import java.io.*;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 1.创建客户端的tcp通信
Socket s = new Socket("10.152.242.223", 12345);
// 2.获取输出流
OutputStream os = s.getOutputStream();
// 3.写数据
//数据来源键盘输入
//BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
//os.write("hello.world".getBytes());
//数据来源于文件
BufferedReader br = new BufferedReader(new FileReader("code\\13.txt"));
String str;
while((str=br.readLine())!=null){
//如果键盘输入886,停止发送
//if(str.equals("886")){
// break;
//}else{
bw.write(str);
bw.newLine();
bw.flush();
//}
}
//告知服务端传输完毕
s.shutdownOutput();
// 客户端接收服务端的反馈
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len;
len=is.read(bys);
System.out.println("服务器的反馈:"+new String(bys,0,len));
s.close();
}
}
- 服务端
package 网络编程.tcp通信;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 1.服务器端
ServerSocket ss= new ServerSocket(12345);
// 2.获取输入流
// 使用ss.accept()方法连接此套接字并接收
Socket s = ss.accept();
// 获取输入流
InputStream is = s.getInputStream();
//byte[] bys = new byte[1024];
//int len;
//len=is.read(bys);
//String s1 = new String(bys, 0, len);
//System.out.println("接收的数据为"+s1);
//通过字符流读数据
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String str;
//数据写入文件
BufferedWriter bw = new BufferedWriter(new FileWriter("code\\14.txt"));
while((str=br.readLine())!=null){
//System.out.println(str);
bw.write(str);
bw.newLine();
bw.flush();
}
//写反馈给客户端
OutputStream os = s.getOutputStream();
os.write("数据已经接收".getBytes());
s.close();
ss.close();
}
}
- 效果图

3.7 为每个客户端都开启一个线程
- 客户端
package 网络编程.tcp通信;
import java.io.*;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 1.创建客户端的tcp通信
Socket s = new Socket("10.152.242.223", 12345);
// 2.获取输出流
OutputStream os = s.getOutputStream();
// 3.写数据
//数据来源键盘输入
//BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
//os.write("hello.world".getBytes());
//数据来源于文件
BufferedReader br = new BufferedReader(new FileReader("code\\13.txt"));
String str;
while((str=br.readLine())!=null){
//如果键盘输入886,停止发送
//if(str.equals("886")){
// break;
//}else{
bw.write(str);
bw.newLine();
bw.flush();
//}
}
//告知服务端传输完毕
s.shutdownOutput();
// 客户端接收服务端的反馈
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len;
len=is.read(bys);
System.out.println("服务器的反馈:"+new String(bys,0,len));
s.close();
}
}
- 服务线程类
package 网络编程.tcp通信;
import java.io.*;
import java.net.Socket;
public class ServerThread implements Runnable{
private Socket s;
public ServerThread(Socket s) {
this.s = s;
}
@Override
public void run() {
// 创建一个字符输入流
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
int count=20;
//输入的文件位置
File file = new File("code\\12" + count + ".txt");
//防止文件重名,如果存在,则使文件名+1
while(file.exists()){
count++;
file = new File("code\\12" + count + ".txt");
}
//写入文件字符流
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(file));
} catch (IOException e) {
e.printStackTrace();
}
String str;
try{
while((str=br.readLine())!=null){
bw.write(str);
bw.newLine();
bw.flush();
}
OutputStream os = s.getOutputStream();
os.write("数据已经接收".getBytes());
s.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
- 服务端
package 网络编程.tcp通信;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo2 {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(12345);
while(true){
// 监听是否有多个客户端,返回多个Socket对象
Socket s = ss.accept();
// 每个对象新建一个线程
new Thread(new ServerThread(s)).start();
}
}
}
- 效果图

浙公网安备 33010602011771号