1 网络编程----TCPNo24
【
public class Server {
public static void main(String[] args){
try {
ServerSocket ss =new ServerSocket(8888);//在8888端口上建立ServerSocket
Socket s =ss.accept();//监听客户端的连接请求,一旦连接请求到达,建立连接,会返回一个服务器端的Socket
InputStream is =s.getInputStream();//获取这个Socket的输入流,用于读取客户端传来的信息
int b = is.read();//读一个字节
System.out.println(b);//打印
s.close();//关闭和客户端的连接
ss.close();//关闭ServerSocket,之后不再去监听端的连接请求
} catch (IOException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
}
public class Client {
public static void main(String[] args){
try {
Socket s = newSocket("127.0.0.1",8881);//向本机8888端口发送连接请求
OutputStream os =s.getOutputStream();//获取客户端Socket的输出流
os.write(100);//写一个字节100
s.close();//关闭套接字
} catch (IOException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
}
】
Protocol协议 就是一种格式、约定,网络两端的主机可以根据这个约定来进行信息的交互和传输
网络四层协议体系架构 TCP/IP
1、应用层 http、ftp
2、传输层 TCP、UDP
3、网络互联层 IP
4、主机到网络层
1.1 基本网络知识
1.1.1 Ip地址
InetAddress类的使用:【
getByName(Stringhost):根据主机名获取IP对象
getHostAddress():获取主机地址
getHostName():获取主机名
getAllByName(Stringhost):获取主机名获取所有的IP对象
getLocalHost():获取本地主机对应的IP地址(127.0.0.1)
示例代码
//在Java中,使用InetAddress类描叙网络地址
InetAddress inetAddr = null;
//创建InetAddress对象
//在互联网上访问服务器有两种形式:1、ip地址 2、主机名(例如:http://www.baidu.com)
// inetAddr =InetAddress.getByName("www.baidu.com");
// inetAddr =InetAddress.getByName("192.168.35.1");
// inetAddr =InetAddress.getByName("192.168.81.144");
// inetAddr = InetAddress.getByName("localhost");
//获取本机ip地址
inetAddr =InetAddress.getLocalHost();
//ip地址
String address =inetAddr.getHostAddress();
//主机名
String host =inetAddr.getHostName();
System.out.println(address+":"+host);
InetAddress[] inetAddresses=InetAddress.getAllByName("www.baidu.com");
for (InetAddress inet :inetAddresses) {
System.out.println(inet.getHostAddress());
}
】
1.1.2 网络编程三要素
【
IP地址:网络中每台主机都必须有一个唯一的IP地址(网络中设备的标识)
端口:用于标识进程的逻辑地址,每个进程都有各自不同的标识, 有效端口0~65535,其中0-1024系统使用或保留端口
传输协议:UDP---《将数据、源地址和目的地址封装在数据报包中;每个数据报的大小被限制在64K以内;不需要建立连接;是不可靠协议,速度快》
TCP----《建立连接,形成传输数据的通道;在连接中进行大数据传输;通过三次握手完成连接;必须建立连接;是可靠协议,效率较低》
【1. 客户端向服务器发送包含初始序列值的数据段,开启通信会话
2. 服务器发送包含确认值的数据段,其值等于收到的序列值加1,并加上其自身的同步序列值
3. 发送带确认值的客户端响应,其值等于接受的序列值加1.这便完成了整个建立连接的过程】
】
1.1.3 Socket(套接字)
1、Socket是为了网络服务而提供的一种机制;
2、套接字是两台机器间通信的端点;
3、网络通信其实就是Socket间的通信(所以网络编程又称为Socket编程);
4、Socket之间通过IO流来进行数据的传输(TCP);
5、Socket = IP地址 + 端口
】
TCP Transmit Control Protocol传输控制协议
可以将IP报文进行包装、组织,有序可靠地传输到网络另一端
是基于连接的,两个主机在进行通信前必须先建立连接(三次握手)
(UDPUser Datagram protocol 用户数据报协议,不需要连接,信息传输会发生丢失)
协议都是跨语言、跨平台的
1.2 Java实现Tcp通信
如何用Java来进行TCP通信:
ServerSocket服务器套接字,用来监听客户端发送来的连接请求,一旦有客户端请求连接,就可以生成一个连接,并获取服务端这头的Socket
构造方法:ServerSocket(int port)在端口port上建立服务端套接字
Socketaccept() 监听客户端过来的连接请求,是一个阻塞方法,连接请求过来了,它就会返回建立的连接的服务端这头的套接字,这个套接字可以用来向客户端写或者从客户端读信息
Socket 套接字,就是网络上两台主机之间建立的连接的两个端点,可以通过它写信息,也可以读信息(套接字可以用于两台连接的主机之间进行通信,读写信息。)
1.2.1 服务端
一:服务端
getOutputStream()获取套接字输出流
write系列方法,使用和文件IO中差不多
getInputStream()获取套接字输入流
read系列方法
1.3 客户端
二:客户端
构造方法:Socket(String address,int port)参数为服务端的地址以及端口号,这样构建时就能发送一个连接请求到服务端,接下来这个创建出来的Socket对象就能用来和服务端通信
getOutputStream()获取套接字输出流
write系列方法,使用和文件IO中差不多
getInputStream()获取套接字输入流
read系列方法
getPort()获取端口号
getInetAddress()获取英特网地址对象(可以调用这个对象的getHostAddress()获取地址字符串)
另有一个4参构造方法Socket(String address,int port,InetAddress addr,int p)可以用第四个参数指定客户端的端口(2参构造方法的客户端端口随机分配)
1.4 实现及理论
Socket类:此类实现客户端套接字
ServerSocket:《此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。
PS:在创建Socket对象时,底层会自动创建一个客户端与服务端之间的通道,这个通道就是Socket流(网络IO流),Socket流既包含输入流,又包含输出流。》
使用步骤:
客户端:【《
1、 创建套接字对象(需要绑定指定的服务器ip地址和端口)
2、 通过IO流和服务端传输数据
3、 关闭Socket,释放资源》
服务端:【《
1、 创建服务端套接字对象(需要绑定端口,以便客户端连接)
2、 等待接收来自客户端的连接请求
3、 通过IO流与客户端传输数据
4、 关闭资源》
】
代码:
【
Client.java客户端
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
// tcp的客户端
System.out.println("tcp客户端开启...");
/*
* 创建Socket对象,当执行这行代码的时候底层会自动和服务端建立连接(三次握手)
* 如果连接建立不成功,就会抛出异常
*/
//Socket socket = newSocket("127.0.0.1", 9999);
Socket socket = new Socket("192.168.81.143", 9999);
// 获取IO流对象,通过IO流对象可以实现与服务端的数据传输
// socket.getInputStream();
OutputStream os = socket.getOutputStream();
os.write("来自tcp客户端的数据".getBytes());
// 释放资源,断开与服务端的连接
socket.close();
System.out.println("tcp客户端关闭...");
}
}
服务端:Server.java
publicclass Server {
public static void main(String[] args)throws IOException {
// tcp的服务端
System.out.println("tcp服务端开启...");
// 创建服务端的套接字对象,用于响应来自客户端的连接请求
ServerSocket serverSocket =new ServerSocket(9999);
// 等待接收来自客户端的连接请求,连接成功后会返回与客户端对应的Socket对象
Socket socket =serverSocket.accept(); // 阻塞式方法
// 获取客户端的ip地址
String ip =socket.getInetAddress().getHostAddress();
System.out.println("与" + ip + "建立连接");
InputStream is =socket.getInputStream();
// socket.getOutputStream();
byte[] buf = new byte[1024];
int length = is.read(buf);
System.out.println(ip +":" + new String(buf, 0, length));
// socket.close();
// 释放资源,关闭服务端的套接字,会断开所有的客户端连接
serverSocket.close();
System.out.println("tcp服务端关闭");
}
}
】
1.5 不间断发送消息到服务器
【
publicclass Client {
public static void main(String[] args)throws UnknownHostException,
IOException {
// tcp的客户端
System.out.println("tcp客户端开启...");
Socket socket = newSocket("192.168.81.143", 9999);
Scanner scanner = newScanner(System.in);
/*BufferedReader br = newBufferedReader(new InputStreamReader(
socket.getInputStream()));*/
BufferedWriter bw = newBufferedWriter(new OutputStreamWriter(
socket.getOutputStream()));
for(;;){
String line =scanner.nextLine();
bw.write(line);
bw.newLine();
bw.flush();
}
// socket.close();
// System.out.println("tcp客户端关闭...");
}
}
publicclass Server {
public static void main(String[] args)throws IOException {
// TODO Auto-generated methodstub
// tcp服务端
System.out.println("TCP服务端开启.....");
ServerSocket serverSocket =new ServerSocket(9999);
Socket socket =serverSocket.accept(); // 阻塞式方法
String ip =socket.getInetAddress().getHostAddress();
System.out.println("与" + ip + "建立连接");
BufferedReader br = newBufferedReader(new InputStreamReader(
socket.getInputStream()));
String line = null;
while((line =br.readLine())!=null){
System.out.println(ip+"发送来:"+line);
}
serverSocket.close();
System.out.println("TCP服务端关闭.....");
}
}
】
1.6 TCP上传文件到服务器
【
publicclass Client {
// TCP的客户端
public static void main(String[] args)throws UnknownHostException,
IOException {
// TODO Auto-generated methodstub
System.out.println("TCP客户端开启.......");
Socket socket = newSocket("192.168.81.143", 9999);
// 将指定的文件上传到服务器
// 一边读取文件数据,一边向服务器端写出数据
BufferedInputStream bis = newBufferedInputStream(new FileInputStream(
"g:\\extras下文件.rar"));
BufferedOutputStream bos =new BufferedOutputStream(socket.getOutputStream());
int b=0;
while((b=bis.read())!=-1){
bos.write(b);
}
bos.close();
bis.close();
socket.close();
System.out.println("TCP客户端关闭.......");
}
}
publicclass Server {
public static void main(String[] args)throws IOException {
// TODO Auto-generated methodstub
System.out.println("tcp服务端开启....");
ServerSocket serverSocket =new ServerSocket(9999);
Socket socket =serverSocket.accept();
String clientName =socket.getInetAddress().getHostName();
BufferedInputStream bis = newBufferedInputStream(
socket.getInputStream());
BufferedOutputStream bos =new BufferedOutputStream(
newFileOutputStream("g:\\" + clientName + ".rar"));
int b = 0;
while((b =bis.read()) !=-1){
bos.write(b);
}
bos.close();
bis.close();
System.out.println("tcp服务端关闭...");
}
}
】
1.7 多用户连接与数据发送
【
publicclass Client {
public static void main(String[] args)throws UnknownHostException,
IOException {
// TODO Auto-generated methodstub
System.out.println("客户端开启./...");
Socket socket = newSocket("192.168.81.144", 6001);
System.out.println("成功与服务器建立连接....");
// 将键盘录入的数据传输到服务器
BufferedReader br = newBufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = newBufferedWriter(new OutputStreamWriter(
socket.getOutputStream()));
//读一行写一行
String line = null; //接收从键盘录入的数据
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
socket.close();
System.out.println("客户端关闭.....");
}
}
//客户端响应线程
publicclass ClientEchoThread extends Thread {
//客户端对应的Socket对象(每个客户端都有自己所对应的Socket对象)
private Socket socket;
private String ip;
public ClientEchoThread(Socket socket){
this.socket = socket;
ip =socket.getInetAddress().getHostAddress();
}
//在线程中执行客户端的响应
@Override
public void run() {
System.out.println("建立与"+ip+"的连接");
BufferedReader br =null;
try {
br =newBufferedReader(new InputStreamReader(socket.getInputStream()));
//读取来自客户端的数据
String line = null;
while((line =br.readLine())!= null){
System.out.println(ip+":"+line);
}
} catch (IOException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}finally{
if(br != null){
try {
br.close();
br= null;
} catch(IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
socket= null;
} catch(IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
*开启几个线程?
* 有几个客户端就有几个线程
*什么时候开线程?
* 一旦有了新的客户端,就需要开启一个新的线程
*线程中应该包含哪些代码?
* 响应客户端的请求
*/
publicclass Server {
public static void main(String[] args)throws IOException {
// TODO Auto-generated methodstub
System.out.println("服务端开启....");
ServerSocket serverSocket = new ServerSocket(6001);
//接收来自客户端的连接请求
//阻塞式方法,一旦有新的客户端连接,就会返回一个客户端对应的Socket对象
//作为客户端,应该不停地去接受客户端的请求
while(true){
Socket socket =serverSocket.accept();
newClientEchoThread(socket).start();
}
// serverSocket.close();
// System.out.println("服务端关闭....");
}
}
】