Socket网络编程
本文将简述计算机网络中IP地址、端口号、资源定位符、数据传输、客户端和服务器的常用模式等概念,与使用套接字编程及url类的常规用法。
一、计算机网络概念
网络:计算机网络是位于不同位置的若干台计算机使用传输介质连接起来,通过传输协议,
实现数据传输和资源共享。
二、Ip地址
计算机网络通过ip唯一区分处于网络中的一台计算机。
三、端口号
计算机中通过端口号来区分软件,端口号在计算中占两个自己,取值范围:0—65535
1、1024以下的端口通常是计算机内置软件端口,类似现实生活中的电话号码120 110
2、1024以上的,我们可以自定义,为了避免重复性,端口号定义的越大越好。
3、使用同种协议的软件之间,端口号不可重复;不同协议,端口号可以重复
四、资源定位
URL统一资源定位符 http://127.0.0.1:80/stusystem/user/1
URI 统一资源修饰符 user/1
五、数据的传输
1、计算机底层通过二进制数据进行通讯。通讯时如识别有效数据,还需不同的协议才能完成。常见的底层协议TCP/IP、 UDP
TCP/IP:类似于打电话,是一种面向连接的协议。特点是安全可靠,效率相对于UDP而言,较为低下。通讯模式为请求响应模式。
UDP:类似于发短信,是一种面向无连接的协议。特点是不可靠,安全性低,但效率高。
UDP是以数据为中心的协议。
2、数据在进行传输时,需要经过一系列的封装和拆分的过程。
(1) 数据的封装
(2) 数据的拆分
采用分层思想,完成对层次的解耦,以及各层的职责分离,让各层合理分工-----OSI七层模型。
六、客户端和服务器
C/S client/Server (胖客户端) 需要安装,需要更新
B/S Browser/Server(瘦客户端) 不需要安装,也不需要更新,服务器更新之后,打开浏览器,自动更新
七、传输层的传输方式
需要解决的问题:OSI七层模型中的二进制数,如何才能到达我们的应用软件
传输层的作用建立一个数据传输通道,将来自于OSI七层模式中的下三层的数据,传输到应用程序中。
这个数据传输通道,我们称之为Socket套接字,类似于现实生活中的传送履带。不过可以双向传输。
作为传输层来讲,只有两种协议:TCP/IP、UDP协议
TCP/IP协议在进行数据传输时,经过3次握手,4次挥手的过程。
TCP
客户端
1、 创建客户端并与服务器建立连接
2、 获取来自服务器的数据
package com.gezhi.net.tcp;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 客户端类
* @author Administrator
*
*/
public class Client {
public static void main(String[] args) {
BufferedReader reader = null;
BufferedWriter out = null;
try {
//与服务器建立连接
Socket client = new Socket("127.0.0.1", 80);
String info = "需要系统资源,请发送给我";
out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
out.write(info);
out.newLine();
out.flush();
//获取来自于服务器的数据
reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
String msg = reader.readLine();//一行一行的读取数据(阻塞式方法)
System.out.println(msg);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
out.close();
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
服务器
1、 创建服务器端 ServerSocket 类+端口
2、 侦听端口,接收来自该端口进入的机器
3、 读取客户端的请求信息
4、 返回数据
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务器类
* @author Administrator
*
*/
public class Server {
public static void main(String[] args) {
ServerSocket ss = null;
BufferedWriter out = null;
BufferedReader reader = null;
try {
//定义本机作为服务器,并针对本机上80这个端口进行数据侦听
ss = new ServerSocket(80);
System.out.println("启动服务器成功,并侦听80端口!!!!!!!!");
//这是一个阻塞式的方法
Socket s = ss.accept();//侦听端口,并接受来自于该端口进入的机器的连接(这个类就好比"履带"对象)
InetAddress addr = s.getInetAddress();//得到客户端IP地址对象
System.out.println(addr.getHostAddress());//打印IP地址(客户端)
System.out.println(addr.getHostName());//打印IP地址|域名|主机名(客户端)
System.out.println("来了一个新的客户端!!!!!!!");
//读取客户端的请求信息
reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
String info = reader.readLine();//一行一行的读取数据(阻塞式方法)
System.out.println("来自于客户端信息:" + info);
//返回数据
String msg = "已接收到您的请求,请等待处理";
out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
out.write(msg);
out.newLine();
out.flush();//刷新缓冲通道
/* while(true) {
}*/
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
UDP
一、 类DatagramSocket DatagramPacket
客户端
- 创建客户端 DatagramSocket 类+端口(指定:数据从哪个端口出去)
- 准备数据,这些数据需要装配到字节数组中区
- 将数据打包DatagramPacket + 服务器地址及端口号 来完成打包
- 发送
- 释放资源
- package com.gezhi.udp;
package com.gezhi.udp;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class MyClient02 {
public static void main(String[] args) {
// TODO Auto-generated method stub
/**
* 建立一个客户端+端口
*/
DatagramSocket client=null;
byte[] data=null;
DatagramPacket packet=null;
try {
client=new DatagramSocket(6666);
double num=98.56;
data=convert2Byte(num);
packet=new DatagramPacket(data, data.length, new InetSocketAddress("127.0.0.1",8888));
client.send(packet);
} catch (Exception e) {
// TODO: handle exception
}
}
/**
* 其他数据类型转换为byte数组
* @param num
* @return
* @throws Exception
*/
private static byte[] convert2Byte(double num) throws Exception {
// TODO Auto-generated method stub
byte[] data=null;
ByteArrayOutputStream bos=new ByteArrayOutputStream();
DataOutputStream dos=new DataOutputStream(bos);
dos.writeDouble(num);
dos.flush();
data=bos.toByteArray();
bos.close();
return data;
}
}
服务端
1.创建服务端 DatagramSocket类+端口(指定:从哪个端口获取数据)
2.准备接收数据 需定义一个字节数组 封装DataGramPacket
3.接收数据
4.分析数据
5.释放资源
package com.gezhi.udp;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* 服务器端
* @author Administrator
*
*/
public class MyServer {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建服务器
DatagramSocket sever=null;
try {
sever=new DatagramSocket(8888);
//准备接收数据
byte[] container=new byte[1024];
DatagramPacket packet=new DatagramPacket(container, container.length);
//接收数据
sever.receive(packet);//阻塞方法
//分析数据
byte[] data=packet.getData();
double nums=covert2Double(data);
System.out.println(nums);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 完成数组到double转换
* @param data
* @return
* @throws IOException
*/
private static double covert2Double(byte[] data) throws IOException {
// TODO Auto-generated method stub
double num=0;
ByteArrayInputStream bis=new ByteArrayInputStream(data);
DataInputStream dis=new DataInputStream(bis);
num=dis.readDouble();
return num;
}
}
URL类
URL(Uniform Resource Locator)代表统一资源定位,代表万维网上的一个资源,例如一个网页或者一个FTP目录。
一个URL实际上是一类URI(Uniform Resource Identifier,统一资源标识符)。URI标识一个资源,但是不包括如何访问该资源的信息。URL标识一个资源以及访问该资源的协议。URI在java中使用java.net.URI类代表。
public static void main(String[] args) {
// TODO Auto-generated method stub
URL url;
try {
url = new URL("https://www.baidu.com:80/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd=java.net.SocketException%3A%20Connection%20reset&rsv_pq=c36f3f840000cf0f&rsv_t=c9f73t9XrpUbpS9A8Qp1mFQ2BEgm2MHPIvB4KT4XvrpUmt%2B9jUE5FUp25KY&rqlang=cn&rsv_enter=1&rsv_n=2&rsv_sug3=1#nextpage.index");
System.out.println("协议:"+url.getProtocol());//获得协议如http,https
System.out.println("主机:"+url.getHost());//获得主机名
System.out.println("端口"+url.getPort());//获得端口号
System.out.println("统一资源修饰符"+url.getFile());//获得url www.baidu.com
System.out.println("查询参数"+url.getQuery());//?后的内容
System.out.println("得到锚点:"+url.getRef());//#后的内容
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}