OSI模型
OSI模型是国际标准化组织(ISO)提出的网络互联模型,OSI模型有7层结构 :
物理层(二进制数据形式传输数据),数据链路层(传输有地址的帧),网络层(路由),传输层(端对端接口,TCP,UDP),会话层,表示层,应用层。
TCP/IP协议
TCP/IP协议的核心是TCP,UDP。
TCP传输 | UDP传输 | |
优点 | 可靠传输,安全,三次握手,不容易丢包 ,一对一,面向连接 | 性能高,传输经济,可实现一对一,一对多或多对一 |
缺点 | 性能比较低 | 不安全,不握手,,容易丢包 |
支持的应用协议 | Telnet,FTP,SMTP等 | NFS,SNMP,DNS,TFTP |
什么时候用到 | 传输少量数据 | 传输大量数据 |
TCP为面向连接,建立连接,通过重传机制,并且还有流量控制和拥塞控制。
UDP为无连接,基本上就给应用程序发送数据包。
TCP服务端:
public class Test {
/**
*服务器端TCP
*/
public static void main(String[] args) throws Exception{
//创建socket的server对象
try(ServerSocket serverSocket = new ServerSocket(8889)) {
while (true){
//等待客户端连接
try(Socket socket = serverSocket.accept()){
//执行这个位置,表示已经连上
InputStreamReader ir = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(ir);
String str = br.readLine();
System.out.println(str);
}catch (Exception e){
e.printStackTrace();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
客户端:
public class Testtcp {
//客户端
public static void main(String[] args) throws IOException {
try (Socket socket = new Socket("127.0.0.1", 8889)) {
OutputStreamWriter ww = new OutputStreamWriter(socket.getOutputStream());//自动将字节流转换成字符
ww.write("www.baidu.com");
ww.write("www.baidu.com");
ww.write("www.baidu.com");
ww.write("www.baidu.com");
ww.flush();
ww.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Tcp服务端
public class TestChatServer {
public static void main(String[] args) throws IOException {
try(ServerSocket serverSocket = new ServerSocket(8889)) { //设置服务端的端口号
BufferedReader reader1 = new BufferedReader(new InputStreamReader(System.in));//输入的新方法,可解决Scanner的不能输出空格问题
System.out.println("服务器已启动,等待连接:");
try (Socket socket = serverSocket.accept()) {//等待接受客户端,接受成功才会走下面的步骤
while (true) {
InputStream is = socket.getInputStream();
Reader reader = new InputStreamReader(is);
BufferedReader br = new BufferedReader(reader);
//上面三行的效果同下一行代码,就是使用输出字符流去接客户端输过来的字节流的信息
// BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message = br.readLine();//一行一行读
System.out.println("服务器收到消息:"+message);
//服务器开始发送消息
OutputStream os = socket.getOutputStream();
OutputStreamWriter ow = new OutputStreamWriter(os);
//上两行与下面一行一样,使用输入字符流输入信息
// OutputStreamWriter ow = new OutputStreamWriter(socket.getOutputStream());
System.err.println("服务器开始发送消息:");
System.out.print("请输入:");
//输出的内容,要带换行,否则readline会一直等
String sendmessage = reader1.readLine();
ow.write(sendmessage+"\n");
ow.flush();
System.out.println("服务器消息已发送..");
if("88".equals(sendmessage)) break; //当输入 88 的时候通信结束
}
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
客户端
public class TestChatClient {
public static void main(String[] args) {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); //输入的方法,类似于Scanner
try (Socket socket = new Socket("10.104.239.29" , 8889)) { //服务端的IP和端口
System.err.println("已经连接上服务端...");
while (true) {
Thread.sleep(10); //睡眠0.01s
System.out.print("请输入信息:");
OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream()); //使用输入流输入要传达的内容
String message = input.readLine();//设置一个String 代表信息
osw.write(message + "\n");//加入到输入流
osw.flush();//
if("88".equals(message)) break;
System.err.println("消息已发送,等待服务器响应...");
//开始接受服务器端消息
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//输出流输出接收到信息,InputStreamReader是连接字节流和字符流的桥梁,BufferReader是字符流
String getmessage = reader.readLine();//一行一行的读取信息
if("88".equals(getmessage)) break;
System.out.println("客户端收到消息..."+getmessage);
}
} catch(IOException e){
e.printStackTrace();
} catch(InterruptedException e){
e.printStackTrace();
}
}
}
UDP服务端
public class UdpServer {
public static void main(String[] args) throws SocketException {
try(DatagramSocket socket = new DatagramSocket(7777)){
//创建一个包用来接收数据
byte[] datas = new byte[1024*1];
DatagramPacket reveivepacket = new DatagramPacket(datas, 0,datas.length);
//阻塞等待一个数据过来
while (true){
socket.receive(reveivepacket);
//接受完毕,输出数据
String ss = new String(reveivepacket.getData(),0,reveivepacket.getLength());
System.out.println(ss);
//响应数据给客户端
byte[] ww = "服务器响应数据".getBytes();
System.out.println("客户端的端口:" + reveivepacket.getPort());
DatagramPacket sendmsg = new DatagramPacket(ww,0,ww.length,reveivepacket.getAddress(),reveivepacket.getPort());
socket.send(sendmsg);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
UDP客户端
public class UdpClient {
public static void main(String[] args) {
try (DatagramSocket socket = new DatagramSocket()) {
//要发的内容
byte[] datas = "dasdasds撒大大sadasd".getBytes();
//构建一个发送包,要指定发送的地址和端口
DatagramPacket datagramPacket = new DatagramPacket(datas, 0, datas.length, InetAddress.getByName("192.168.0.5"), 7777);
//开始发送数据
socket.send(datagramPacket);
//开始接受服务器的数据
byte[] data = new byte[1024*1];
DatagramPacket reveivemsg = new DatagramPacket(data,0,data.length );
socket.receive(reveivemsg);
String revemsg = new String(reveivemsg.getData(),0,reveivemsg.getLength());
System.out.println(revemsg);
} catch (Exception e) {
e.printStackTrace();
}
}
}