Java网络编程:socket tcp编程

Socket

传输协议

UDP协议:用户数据报协议

  • 面向无连接、不可靠、无序的数据
  • 以数据报作为数据传输的载体

传输数据时,首先将要传输的数据定义成数据报(Datagram),在数据报中指明要达到的socket(主机地址和端口号),然后再将数据发出。
类:
DatagramPacket——表示数据报包
DatagramSocket——进行端到端通信

TCP协议:传输控制协议

  • 面向连接、可靠、有序的数据流
  • 以字节流的方式发送数据

类:
客户端——Socket类
服务端——ServerSocket类

socket

Socket:网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定

socket 通信模型

(1) 创建Socket;
(2) 打开连接到Socket的输入/出流;
(3) 按照一定的协议对Socket进行读/写操作;
(4) 关闭Socket.

这里写图片描述

建立连接,收发数字字符串

使用 Socket(套接字)进行不同的程序之间的通信
1. 服务端开启8888端口,并监听着,时刻等待着客户端的连接请求
2. 客户端知道服务端的ip地址和监听端口号,发出请求到服务端
客户端的端口地址是系统分配的,通常都会大于1024
一旦建立了连接,服务端会得到一个新的Socket对象,该对象负责与客户端进行通信。
注意: 在开发调试的过程中,如果修改过了服务器Server代码,要关闭启动的Server,否则新的Server不能启动,因为8888端口被占用了。

1 服务器

package socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) {
        try {
            // 创建服务端Socket,即ServerSocket
            // 指定绑定的端口,并监听此端口
            ServerSocket ss = new ServerSocket(8888);

            // 在8888端口监听,看是否有请求过来
            System.out.println("监听端口号:8888");
            Socket s = ss.accept();

            // 打开输入流
            InputStream is = s.getInputStream();

//          // 读取数字
//          int msg = is.read();
//          System.out.println(msg);
//          is.close();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String info = null;
            while((info = br.readLine()) != null){
                System.out.println("客户端发来消息:" + info);
            }
            s.shutdownInput(); // 关闭输入流

            br.close();
            is.close();
            s.close(); // 关闭与客户端的连接,但服务端还在运行,IO资源不会释放
            ss.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2 客户端

package socket;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
    public static void main(String[] args) {
        try {
            // 连接到本机的8888端口
            Socket s = new Socket("127.0.0.1", 8888);
            //
            OutputStream os = s.getOutputStream();

//          // 写出数字
//          os.write(110);

            PrintWriter pw = new PrintWriter(os);
            pw.write("用户名:admin,密码:123");
            pw.flush();
            s.shutdownInput();  // 关闭输出流

            pw.close();
            os.close();
            s.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用Scanner

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) {
        try {
            // 连接到本机的8888端口
            Socket s = new Socket("127.0.0.1", 8888);
            //
            OutputStream os = s.getOutputStream();

            DataOutputStream dos = new DataOutputStream(os);

            // 使用Scanner读取控制台的输入,并发送到服务端
            Scanner sc = new Scanner(System.in);

            String str = sc.next();
            dos.writeUTF(str);

            dos.close();
            s.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行结果

监听端口号:8888
客户端发来消息:lizhongping

例:服务端和客户端互聊

服务端

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Server {
    public static void main(String[] args) {
        try {
            // 创建服务端Socket,即ServerSocket
            // 指定绑定的端口,并监听此端口
            ServerSocket ss = new ServerSocket(8888);

            // 在8888端口监听,看是否有请求过来
            System.out.println("监听端口号:8888");
            Socket s = ss.accept();

            // 打开输入流
            InputStream is = s.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            OutputStream os = s.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            while (true) {
                String msg = dis.readUTF();
                System.out.println("收到客户端信息:" + msg);
                Scanner sc = new Scanner(System.in);
                String str = sc.next();
                dos.writeUTF(str);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) {
        try {
            // 连接到本机的8888端口
            Socket s = new Socket("127.0.0.1", 8888);
            //
            OutputStream os = s.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            InputStream is = s.getInputStream();
            DataInputStream dis = new DataInputStream(is);

            while (true) {
                Scanner sc = new Scanner(System.in);
                String str = sc.next();
                dos.writeUTF(str);
                String msg = dis.readUTF();
                System.out.println("收到服务端信息" + msg);
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注:我们可以明显的注意到问题所在:由于单线程的缘故,同一时间,要么收信息,要么发信息,不能同时进行。需要通过【多线程】改进。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值