您的位置:首页 > 理论基础 > 计算机网络

Java Socket网络编程(二)

2017-09-05 11:19 232 查看
Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务端的沟通变成了现实,而在网络编程中,使用最多的就是Socket。像大家熟悉的QQ,MSN都使用了Socket相关技术.

TCP编程 

1、TCP协议是面向连接的、可靠的、有序的、以字节流的方式发送数据,通过三次握手方式建立连接,形成传输数据的通道,在连接中进行大量数据的传输,效率会稍低 

2、Java中基于TCP协议实现网络通信的类 
客户端的Socket类 
服务器端的ServerSocket类



3、Socket通信的步骤 
① 创建ServerSocket和Socket 
② 打开连接到Socket的输入/输出流 
③ 按照协议对Socket进行读/写操作 
④ 关闭输入输出流、关闭Socket 

4、服务器端: 
① 创建ServerSocket对象,绑定监听端口 
② 通过accept()方法监听客户端请求 
③ 连接建立后,通过输入流读取客户端发送的请求信息 
④ 通过输出流向客户端发送乡音信息

import java.io.IOException;

import java.net.InetAddress;

import java.net.ServerSocket;

import java.net.Socket;

/*

 * 基于TCP协议的Socket通信,实现用户登陆

 * 服务器端

 */

public class Server {
public static void main(String[] args) {

    try {

        //1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口

        S
4000
erverSocket serverSocket=new ServerSocket(8888);

        Socket socket=null;

        //记录客户端的数量

        int count=0;

        System.out.println("***服务器即将启动,等待客户端的连接***");

        //循环监听等待客户端的连接

        while(true){

           //调用accept()方法开始监听,等待客户端的连接

            socket=serverSocket.accept();

            //创建一个新的线程

            ServerThread serverThread=new ServerThread(socket);

            //启动线程

            serverThread.start();

            count++;//统计客户端的数量

            System.out.println("客户端的数量:"+count);

            InetAddress address=socket.getInetAddress();

            System.out.println("当前客户端的IP:"+address.getHostAddress());

        }

    } catch (IOException e) {

        e.printStackTrace();

    }

  }

}

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.PrintWriter;

import java.net.Socket;

/*

 * 服务器线程处理类

 */

public class ServerThread extends Thread {
// 和本线程相关的Socket
Socket socket = null;

public ServerThread(Socket socket) {

    this.socket = socket;

}

//线程执行的操作,响应客户端的请求

public void run(){

    InputStream is=null;

    InputStreamReader isr=null;

    BufferedReader br=null;

    OutputStream os=null;

    PrintWriter pw=null;

    try {

        //获取输入流,并读取客户端信息

        is = socket.getInputStream();

        isr = new InputStreamReader(is);

        br = new BufferedReader(isr);

        String info=null;

        while((info=br.readLine())!=null){//循环读取客户端的信息

            System.out.println("我是服务器,客户端说:"+info);

        }

        socket.shutdownInput();//关闭输入流

        //获取输出流,响应客户端的请求

        os = socket.getOutputStream();

        pw = new PrintWriter(os);

        pw.write("欢迎您!");

        pw.flush();//调用flush()方法将缓冲输出

    } catch (IOException e) {

        // TODO Auto-generated catch block

        e.printStackTrace();

    }finally{

        //关闭资源

        try {

            if(pw!=null)

                pw.close();

            if(os!=null)

                os.close();

            if(br!=null)

                br.close();

            if(isr!=null)

                isr.close();

            if(is!=null)

                is.close();

            if(socket!=null)

                socket.close();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

}

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

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 {

        //1.创建客户端Socket,指定服务器地址和端口

        Socket socket=new Socket("localhost", 8888);

        //2.获取输出流,向服务器端发送信息

        OutputStream os=socket.getOutputStream();//字节输出流

        PrintWriter pw=new PrintWriter(os);//将输出流包装为打印流

        pw.write("用户名:alice;密码:789");

        pw.flush();

        socket.shutdownOutput();//关闭输出流

        //3.获取输入流,并读取服务器端的响应信息

        InputStream is=socket.getInputStream();

        BufferedReader br=new BufferedReader(new InputStreamReader(is));

        String info=null;

        while((info=br.readLine())!=null){

            System.out.println("我是客户端,服务器说:"+info);

        }

        //4.关闭资源

        br.close();

        is.close();

        pw.close();

        os.close();

        socket.close();

    } catch (UnknownHostException e) {

        e.printStackTrace();

    } catch (IOException e) {

        e.printStackTrace();

    }

}

}

打印台输出:

服务器即将启动,等待客户端的连接 

00 

客户端的数量:1 

当前客户端的IP:127.0.0.1 

我是服务器,客户端说:用户名:alice;密码:789 

客户端的数量:2 

当前客户端的IP:127.0.0.1 

我是服务器,客户端说:用户名:alice;密码:789 

客户端的数量:3 

当前客户端的IP:127.0.0.1 

我是服务器,客户端说:用户名:alice;密码:789

UDP编程 

UDP协议(用户数据报协议)是无连接的、不可靠的、无序的,速度快 

进行数据传输时,首先将要传输的数据定义成数据报(Datagram),大小限制在64k,在数据报中指明数据索要达到的Socket(主机地址和端口号),然后再将数据报发送出去 

DatagramPacket类:表示数据报包 

DatagramSocket类:进行端到端通信的类 

1、服务器端实现步骤 
① 创建DatagramSocket,指定端口号 
② 创建DatagramPacket 
③ 接受客户端发送的数据信息 
④ 读取数据 

2、客户端实现步骤
① 定义发送信息 
② 创建DatagramPacket,包含将要发送的信息 
③ 创建DatagramSocket 
④ 发送数据

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

 /*

  * 服务器端,实现基于UDP的用户登陆

  */

public class UDPServer {

public static void main(String[] args) throws IOException {

    /*

     * 接收客户端发送的数据

     */

    //1.创建服务器端DatagramSocket,指定端口

    DatagramSocket socket=new DatagramSocket(8800);

    //2.创建数据报,用于接收客户端发送的数据

    byte[] data =new byte[1024];//创建字节数组,指定接收的数据包的大小

    DatagramPacket packet=new DatagramPacket(data, data.length);

    //3.接收客户端发送的数据

    System.out.println("****服务器端已经启动,等待客户端发送数据");

    socket.receive(packet);//此方法在接收到数据报之前会一直阻塞

    //4.读取数据

    String info=new String(data, 0, packet.getLength());

    System.out.println("我是服务器,客户端说:"+info);

    /*

     * 向客户端响应数据

     */

    //1.定义客户端的地址、端口号、数据

    InetAddress address=packet.getAddress();

    int port=packet.getPort();

    byte[] data2="欢迎您!".getBytes();

    //2.创建数据报,包含响应的数据信息

    DatagramPacket packet2=new DatagramPacket(data2, data2.length, address, port);

    //3.响应客户端

    socket.send(packet2);

    //4.关闭资源

    socket.close();

}

}

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

/*

 * 客户端

 */

public class UDPClient {

public static void main(String[] args) throws IOException {

    /*

     * 向服务器端发送数据

     */

    //1.定义服务器的地址、端口号、数据

    InetAddress address=InetAddress.getByName("localhost");

    int port=8800;

    byte[] data="用户名:admin;密码:123".getBytes();

    //2.创建数据报,包含发送的数据信息

    DatagramPacket packet=new DatagramPacket(data, data.length, address, port);

    //3.创建DatagramSocket对象

    DatagramSocket socket=new DatagramSocket();

    //4.向服务器端发送数据报

    socket.send(packet);

    /*

     * 接收服务器端响应的数据

     */

    //1.创建数据报,用于接收服务器端响应的数据

    byte[] data2=new byte[1024];

    DatagramPacket packet2=new DatagramPacket(data2, data2.length);

    //2.接收服务器响应的数据

    socket.receive(packet2);

    //3.读取数据

    String reply=new String(data2, 0, packet2.getLength());

    System.out.println("我是客户端,服务器说:"+reply);

    //4.关闭资源

    socket.close();

}

 }

控制台打印: 

我是客户端,服务器说:欢迎您!

注意问题:

1、多线程的优先级问题: 

根据实际的经验,适当的降低优先级,否侧可能会有程序运行效率低的情况 

2、是否关闭输出流和输入流: 

对于同一个socket,如果关闭了输出流,则与该输出流关联的socket也会被关闭,所以一般不用关闭流,直接关闭socket即可 

3、使用TCP通信传输对象,IO中序列化部分 

4、socket编程传递文件,IO流部分
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: