------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、计算机网络与网络编程
1、计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
2、网络编程就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
二、网络模型
1、计算机网络之间以何种规则进行通信,就是网络模型研究问题。
2、网络模型一般是指
A、OSI(Open System Interconnection开放系统互连)参考模型
B、TCP/IP参考模型
一、网络三要素
1、IP地址:网络中设备的标识,不易记忆,可用主机名。
要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接受数据的计算机和识别发送的计算机,在TCP/IP协议中,这个标识号就是IP地址。
2、端口号:用于标识进程的逻辑地址,不同进程的标识。
A、物理端口:网卡口
B、逻辑端口:就是我们所指的逻辑端口
每个网络程序都会至少有一个逻辑端口
用于标识进程的逻辑地址,不同进程的标识
有效端口:0~65535,其中0~1024系统使用或保留端口。
3、传输协议:通讯的规则,常见协议:TCP,UDP。
UDP:将数据源和目的封装成数据包中,不需要建立连接;每个数据报的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快。
TCP:建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低。
四、Socket
1、在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。
2、Socket就是为网络编程提供的一种机制,又叫套接字编程。
A、通信的两端都有Socket。
B、网络通信其实就是Socket间的通信。
C、数据在两个Socket间通过IO传输。
五、InetAddress类:是对IP地址的抽象
1、无构造方法
2、主要方法
public static InetAddress getLocalHost() throws UnknownHostException 获取本地主机
public static InetAddress getByName(String host) throws UnknownHostException 依据主机名获取主机
public String getHostName()
public String getHostAddress()
3、代码体现:
import java.net.*;
class IPDemo {
public static void main(String[] args) throws Exception{
InetAddress inetAddress = InetAddress.getLocalHost();
System.out.println(inetAddress);
//获取IP地址
System.out.println("Address:"+inetAddress.getHostAddress());
//获取主机名
System.out.println("name:"+inetAddress.getHostName());
//获取百度IP地址
InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress2);
InetAddress[] iAddressArray = InetAddress.getAllByName("www.baidu.com");
for (InetAddress iAddress : iAddressArray) {
// 获取主机名
String name = iAddress.getHostName();
// 获取主机IP地址
String address = iAddress.getHostAddress();
System.out.println(name + "***" + address);
}
}
}
六、UDP网络编程操作
1、DatagramSocket数据套接字与DatagramPacket数据包
2、步骤:
建立发送端,接收端。
创建数据
建立数据包。
调用Socket的发送接收方法。
关闭Socket。
3、发送端与接收端是两个独立的运行程序。
4、UDP发送端格式代码:
public static void main(String[] args) throws Exception
{
//建立udp服务,发送端并没有指定端口,会自动分配一个端口
DatagramSocket ds = new DatagramSocket();
//定义数据内容,并将数据封装成数据包
byte[] bys = "Bruce Lee and Jet Li".getBytes();
//发送必须明确主机
DatagramPacket dp = new DatagramPacket(bys,bys.length,InetAddress.getByName("192.168,1,100"),8888);
//通过udp的socket服务中的功能完成数据包的发送
ds.send(dp);
//关闭资源
ds.close();
}
UDP接收端格式代码:
public static void main(String[] args) throws Exception
{
//定义Socket服务,并监听一个端口,明确哪些是应用程序可以处理的
DatagramSocket ds = new DatagramSocket(8888);
//预先定义好一个数据包,用于存储接收到的数据
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
//通过udp的socket服务中的receive方法将接受到的数据存储到数据包中
ds.receive(dp);
//通过数据包对象的方法获取其中的数据内容,包括地址,端口,数据主体
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String data = new String(dp.getData(),0,dp.getLength());
System.out.println(ip+":"+port":"+data);
//关闭资源
ds.close();
}
七、TCP网络编程操作
1、Socket客户端和ServerSocket服务器端
2、步骤:
建立客户端和服务器端。
建立连接后,通过Socket中的IO流(Socket流)进行数据的传输。
(如果是服务器端,则需要添加一步操作:通过Socket服务获取Sokect再获取其当中的IO流)
关闭socket。
3、注意:
客户端与服务器端是两个独立的应用程序。
服务器端开启后等待客户端访问,不应关闭。
一个服务器端对应多个客户端。
不同客户端间通信可以通过服务器端中转信息。
4、TCP的3次握手
第一次:建立连接时,客户端发送SYN包到服务器,并进入发送状态,等待服务器确认
第二次:服务器收到SYN包,必须确认客户的SYN,同时自己也送一个SYN包,即SYN+ACK包,此时服务器进入接受状态
第三次:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK,此包发送完毕,客户端和服务器进入已建立状态,完成三次握手
5、TCP服务器端格式代码
public static void main(String[] args) throws Exception
{
//建立服务端对象,监听一个端口
ServerSocket server = new ServerSocket(8888);
//通过accept方法获取客户端对象
Socket client = server.accept();
String ip = client.getInetAddress().getHostAddress();
Systme.out.println(ip+"...connected");
//获取socket的读取流,读取客户端发送过来的数据
InputStream is = client.getInputSteam();
//读取数据的基本操作
byte[] bys = new byte[1024];
int len = is.read(bys);
String str = new String(bys,0,len);
System.out.println(str);
//关闭资源
client.close();
server.close();
}
TCP客户端格式代码
public static void main(String[] args) throws Exception
{
//建立客户端Socket服务,并去进行目的地址连接
//这个步骤只有一执行,就已经连出去了,开始三次握手了
Socket client = new socket("192.168.1.100",8888);
//通过Socket对象的方法获取输出流对象
OutputStream os = cilent.getOutputStream();
//将数据写入流中
os.write("Bruce Lee".getBytes());
//关闭资源
client.close();
//os是由client建立的,client关闭了,os就关闭了,所以不用单独关
}
6、TCP传输容易出现的问题
客户端连接上服务端,两端都在等待,没有任何数据传输。
原因:因为read方法或者readLine方法是阻塞式。
解决办法:自定义结束标记;使用hutdownInput,shutdownOutput
案例:服务器端接收数据,写到文件中,回复信息:数据已收到!
//服务端
package cn.itcast6;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) throws Exception {
//创建ServerSocket对象
ServerSocket ss = new ServerSocket(60000);
//获取socket
Socket clientSocket = ss.accept();
//获取输入流,读取客户端信息。创建字符输出流,将内容写入到一个文件中。
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
String line;
while((line = br.readLine())!=null) {
bw.write(line);
bw.newLine();
bw.flush();
}
//返回接到数据的响应
OutputStream outputStream = clientSocket.getOutputStream();
outputStream.write("数据已收到,请放心!".getBytes());
//关闭
clientSocket.close();
}
}
//客户端
package cn.itcast6;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.net.InetAddress;
import java.net.Socket;
public class TCPClient {
public static void main(String[] args) throws Exception {
//创建Socket对象
InetAddress focusIP = InetAddress.getByName("192.168.21.89");
int focusPort = 60000;
Socket socket = new Socket(focusIP, focusPort);
//从控制才输入信息,写到Socket中的输出流中去。
//创建输入流对象,从控制台读取信息
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//创建输出流对象,写到socket当中的输出流中
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String line;
while(true) {
//读取一行
line = br.readLine();
//如果控制台输出over,标志着客户端不再输入内容了,应该结束循环
if("over".equals(line)) {
break;
}
//写出一行
bw.write(line);
bw.newLine();
bw.flush();
}
//告诉服务器端,不再输出了,我已经关闭了输出
socket.shutdownOutput();
//从socket的输入流中读取服务器端返回的数据
Reader reader = new InputStreamReader(socket.getInputStream());
char[] chars = new char[1024];
int len;
while((len=reader.read(chars))!=-1){
System.out.println(new String(chars,0,len));
}
//关闭资源
socket.close();
}
}