Java Socket网络编程(二)

来源:互联网 发布:英迈零售软件 编辑:程序博客网 时间:2024/05/09 22:21

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,指定绑定的端口,并监听此端口
        ServerSocket 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流部分



原创粉丝点击