网络编程- socket编程 -TCP编程

第二节 TCP编程

2.1 URL统一资源定位符

URL(Uniform Resource Locator)
统一资源定位符,由4部分组成:协议 、存放资源的主机域名****、端口号资源文件名
URL是指向互联网“资源”的指针。
资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。

【示例3】URL类的使用

public class TestURL {
    public static void main(String[] args) throws IOException {
      //URL url = new   
//URL("https://www.bjsxt.com:90/news/11068.html?name=zhsan&pwd=lisi");
     URL url = new URL("https://www.bjsxt.com:90/news/11068.html#cloths");
        System.out.println(url.getProtocol());
        System.out.println(url.getHost());
        System.out.println(url.getPort());
        System.out.println(url.getDefaultPort());
        System.out.println(url.getPath());
        System.out.println(url.getQuery());
        System.out.println(url.getRef());
        System.out.println(url.getAuthority());
        System.out.println(url.getContent());
        System.out.println(url.getFile());
    }
}

2.2 Socket套接字

套接字Socket
我们开发的网络应用程序位于应用层,TCP和UDP属于传输层协议,在应用层如何使用传输层的服务呢?在应用层和传输层之间,则是使用套接字来进行分离。
套接字就像传输层为应用层开的一个小口,应用程序通过这个小口向远程发送数据,或接收远程发来数据;而这个小口以内,也就是数据进入这个口之后,或者数据从这个口出来之前,是不知道也不需要知道的,也不会关心它如何传输,这属于网络其它层次的工作。
在这里插入图片描述
在这里插入图片描述

Socket实际是传输层供给应用层的编程接口。传输层则在网络层的基础上提供进程到进程问的逻辑通道,而应用层的进程则利用传输层向另一台主机的某一进程通信。Socket就是应用层与传输层之间的桥梁
使用Socket编程可以开发客户机和服务器应用程序,可以在本地网络上进行通信,也可通过Internet在全球范围内通信。

生活案例1:
如果你想写封邮件发给远方的朋友,如何写信、将信打包,属于应用层。信怎么写,怎么打包完全由我们做主;
而当我们将信投入邮筒时,邮筒的那个口就是套接字,在进入套接字之后,就是传输层、网络层等(邮局、公路交管或者航线等)其它层次的工作了。我们从来不会去关心信是如何从西安发往北京的,我们只知道写好了投入邮筒就OK了。

生活案例2:
如果你想发货给国外,你只要把货物放入集装箱,然后交给码头就可以了。发送什么货物,货物如何打包,完全有你做主。
码头就是套接字,剩下的事情就交给港口和货运公司处理就行了,具体细节我们无需了解。

2.3 TCP编程-一次单向通信

功能:实现类似QQ、微信、邮箱、商城的网络登录功能,可以多个用户同时登录。为了便于理解,进行功能分解和迭代,分为一次单向通信、一次双向通信、传输对象、引入多线程来实现。


在这里插入图片描述

【示例4】网络登录-一次单向通信

public class LoginServer {
    public static void main(String[] args) throws IOException {
        //1.创建一个ServerSocket,负责监听客户端请求
        ServerSocket serverSocket = new ServerSocket(8800);
        //2.使用ServerSocket进行监听
        Socket socket = serverSocket.accept();//请求未到,在此阻塞
        //3.处理用户的请求
        InputStream is = socket.getInputStream();
        DataInputStream dis = new DataInputStream(is);
        String result = dis.readUTF();
        System.out.println("这里是服务器端:"+result);
        //4.关闭资源
        dis.close();
//        is.close();
//        socket.close();   serverSocket.close();
    }
}
public class LoginClient {
    public static void main(String[] args) throws IOException {
        //1.创建一个Socket,指明服务器端的IP地址和端口号
        Socket socket = new 
Socket(InetAddress.getByName("192.168.153.253"),8800);
        //2.向服务器端发起一个新的请求
        OutputStream os = socket.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        dos.writeUTF("username=bjsxt&password=bjsxt");
        //3.关闭资源
        dos.close();
//        os.close();
//        socket.close();
    }
}

2.4 TCP编程-一次双向通信

【示例5】网络登录-一次双向通信

public class LoginServer {
    public static void main(String[] args) throws IOException {
        //1.创建一个ServerSocket,负责监听客户端请求
        ServerSocket serverSocket = new ServerSocket(8800);
        //2.使用ServerSocket进行监听
        Socket socket = serverSocket.accept();//请求未到,在此阻塞
        //3.处理用户的请求
        InputStream is = socket.getInputStream();
        DataInputStream dis = new DataInputStream(is);
        String result = dis.readUTF();
        System.out.println("这里是服务器端:"+result);
        //4.给出客户端响应
        OutputStream os = socket.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        dos.writeUTF("您好,登录成功,欢迎您");
        //5.关闭资源
        dis.close();
        dos.close();
    }
}
public class LoginClient {
    public static void main(String[] args) throws IOException {
        //1.创建一个Socket,指明服务器端的IP地址和端口号
        Socket socket = new 
Socket(InetAddress.getByName("192.168.153.253"),8800);
        //2.向服务器端发起一个新的请求
        OutputStream os = socket.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        dos.writeUTF("username=bjsxt&password=bjsxt");
        //3.接收来自服务器端的响应
        InputStream is = socket.getInputStream();
        DataInputStream dis = new DataInputStream(is);
        String result = dis.readUTF();
        System.out.println("这里是客户端:"+result);
        //3.关闭资源
        dis.close();
dos.close();
    }
}

第三节 TCP编程

3.1TCP编程-传输对象

在一次双向通信基础上进步优化,在客户端输入用户名和密码,并封装到User对象中。如何在TCP编程中传输对象呢?

【示例6】网络登录-传输对象

public class User implements Serializable {
    private String userId;
    private String password;
}
public class LoginServer {
    public static void main(String[] args) 
throws IOException, ClassNotFoundException {
        //1.创建一个ServerSocket,负责监听客户端请求
        ServerSocket serverSocket = new ServerSocket(8800);
        //2.使用ServerSocket进行监听
        Socket socket = serverSocket.accept();//请求未到,在此阻塞
        //3.处理用户的请求
        InputStream is = socket.getInputStream();
        ObjectInputStream ois = new ObjectInputStream(is);
        User user = (User)ois.readObject();
        System.out.println("这里是服务器端:"+user);
        //4.给出客户端响应
        OutputStream os = socket.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        if(user.getUserId().indexOf("sxt")>=0){
            dos.writeUTF("您好,登录成功,欢迎您");
        }else{
            dos.writeUTF("您好,登录失败,请重新输入");
        }
        //4.关闭资源
        ois.close();
        dos.close();
    }
}
public class LoginClient {
    public static void main(String[] args) throws IOException {
        //1.创建一个Socket,指明服务器端的IP地址和端口号
        Socket socket = 
new Socket(InetAddress.getByName("192.168.153.253"),8800);
        //从键盘输入用户名和密码,封装到User对象中
        Scanner input = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String userId = input.next();
        System.out.println("请输入密码:");
        String password = input.next();
        User user = new User(userId,password);
        //2.向服务器端发起一个新的请求
        OutputStream os = socket.getOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(os);
        oos.writeObject(user);
        //3.接收来自服务器端的响应
        InputStream is = socket.getInputStream();
        DataInputStream dis = new DataInputStream(is);
        String result = dis.readUTF();
        System.out.println("这里是客户端:"+result);
    //3.关闭资源
        dis.close();
        oos.close();
    }
}


使用TCP实现网络登录功能总结

服务器创建ServerSocket,在指定端口监听并并处理请求;
ServletSocket通过accept() 接收用户请求并返回对应的Socket,否则一种处于监听等待状态,线程也被阻塞
客户端创建Socket,需要指定服务器的ip和端口号,向服务器发送和接收响应
客户端发送数据需输出流(写),客户端获取反馈数据需输入流(读)
服务端反馈数据需输出流(写),服务端获取请求数据需输入流(读)
一旦使用ServerSocket和Socket建立了网络连接后,网络通信和普通IO流操作并没有太大区别
网络通信输出流建议使用DataOutputStream和ObjectOutputStream,与平台无关,输入流相应使用DataIntputStream和ObjectInputStream
如果是字符串通信也可以使用BufferedReader和PrintWriter,简单方便

3.2 TCP编程-引入多线程

实现应用中,服务器端一周处于运行状态,并且会出现多个用户同时登录的情况,需要服务器端进行处理。
引入多线程,服务器端收到请求后,开辟一个新的线程,实现对用户请求的处理。
【示例7】网络登录-引入多线程

public class LoginThread extends  Thread {
    private Socket socket;
    public LoginThread(Socket socket) {
        this.socket = socket;
    }
    public void run() {
        ObjectInputStream ois = null;
        DataOutputStream dos = null;
        try{
            ois = new ObjectInputStream(socket.getInputStream());
          dos = new DataOutputStream(socket.getOutputStream());
            //3.处理用户的请求
            User user = (User)ois.readObject();
            //4.给出客户端响应
            if(user.getUserId().indexOf("sxt")>=0){
                dos.writeUTF("您好,登录成功,欢迎您");
            }else{
                dos.writeUTF("您好,登录失败,请重新输入");
            }
        }catch(IOException e){
           e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            //4.关闭资源
            try {
                if(ois != null){
                    ois.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(dos != null){
                    dos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
public class LoginServer {
    public static void main(String[] args) 
throws IOException, ClassNotFoundException {
        //1.创建一个ServerSocket,负责监听客户端请求
        ServerSocket serverSocket = new ServerSocket(8800);
        int i = 0;
        while(true){
            //2.使用ServerSocket进行监听
          Socket socket = serverSocket.accept();//请求未到,在此阻塞
            //3.创建一个新的线程来处理请求
            Thread thread = new LoginThread(socket);
            thread.start();
            //4.输出请求的次数,客户端的ip地址
            String ip = socket.getInetAddress().getHostAddress();
   System.out.println("这是第"+(++i)+"次访问,对方的IP地址是:"+ip);
      }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值