java Socket实现简单的服务端和客户端

一、使用Socket和ServerSocket编写简易的客户端和服务端并实现双向通信

    1 使用ServerSocket建立一个服务端:
    
        1.1 需要绑定一个未使用的端口
            ServerSocket serverSocket = new ServerSocket(9999);
            此时,主机会在9999端口上监听来自客户端的连接请求,操作系统会将接受到了请求放入一个先进先出的队列中,在ServerSocket的其它构造方式中有一个参数backlog,就是用来指定这个队列的大小的,默认为50。当请求数超过这个队列大小时,服务端会拒绝客户端的请求。
            
        1.2 调用accept()方法,获取一个Socket实例,这时候服务端就和客户端之间建立的通信。
            Socket socket = serverSocket.accept();
            
        1.3 通过socket.getInputStream()获取输入流,之后可以在输入流中获取到客户端传输过来的数据
            InputStream is = socket.getInputStream();
            读取完毕后调用socket.shutdownInput()关闭输入
        
        1.4 通过socket.getOutputStream()获取输出流,之后可以通过这个输出流向客户段返回数据
            OutputStream os = socket.getOutputStream();
            写操作完成后需要调用socket.shutdownOutput()关闭输出
        
        1.5 关闭socket
            socket.close();
        
        1.6 关闭服务:一般会在finally块中去关闭
            serverSocket.close();

下面是服务端代码:


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 
 * @author Administrator
 *
 */
public class SimpleServer {
	
	private final static String MESSAGE = "Hello Client";

	public static void main(String[] args) {
		
		ServerSocket serverSocket = null;
		
		try {
			serverSocket = new ServerSocket(9999);
			System.out.println("server started");
			Socket socket = null;
			
			while(true) {
				//通过accept获取一个Socket实例并建立一客户段的连接
				socket = serverSocket.accept();
				
				System.out.println("read a message from stream");
				//获取输入流,读取客户端传输的数据
				InputStream is = socket.getInputStream();
				
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				byte[] bt = new byte[256];
				int n = -1;
				//当客户端关闭其输出流时,read会返回-1
				while((n = is.read(bt)) != -1) {
					baos.write(bt, 0, n);
				}
				//关闭输入
				socket.shutdownInput();
				
				//传输字符,一般情况下必须指定字符编码
				System.out.println("message:" + new String(baos.toByteArray(), "UTF-8"));
				
				System.out.println("return a message to client");
				//获取输出流,向客户端返回数据
				OutputStream os = socket.getOutputStream();
				
				os.write(MESSAGE.getBytes("UTF-8"));
				
				//此处需要关闭输出,否则客户端的读操作将一直循环下去
				socket.shutdownOutput();
				
				//关闭socket
				socket.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(null != serverSocket) {
					serverSocket.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			System.out.println("finished...");
		}
	}
}

2.使用Socket创建一个客户端,并向服务端发送请求
    
        2.1 使用Socket建立客户端,需要指定服务器地址和端口
            Socket socket = new Socket("127.0.0.1", 9999);
            
        2.2  通过socket.getOutputStream()获取输出流,向服务端传输数据
            OutputStream os = socket.getOutputStream();
            写操作完成后需要调用socket.shutdownOutput()关闭输出
            
        2.3 通过socket.getInputStream()获取输入流,并从输入流中获取服务端返回的数据
            InputStream is = socket.getInputStream();
            读取完毕后调用socket.shutdownInput()关闭输入
            
        2.4 关闭socket
            socket.close();

下面是客户段代码:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * 
 * @author Administrator
 *
 */
public class SimpleClient {
	
	private final static String MESSAGE = "hello server";

	public static void main(String[] args) {
		
		Socket socket = null;
		OutputStream os = null;
		InputStream is = null;
		try {
			socket = new Socket("127.0.0.1", 9999);
			System.out.println("successed to connect to server");
			System.out.println("send a message to server");
			//获取输出流,向服务端发送数据
			os = socket.getOutputStream();
			//传输字符,一般情况下必须指定字符编码
			os.write(MESSAGE.getBytes("UTF-8"));
			
			//此处需要关闭输出,否则服务端的读操作将一直循环下去
			socket.shutdownOutput();
			
			System.out.println("read a message from stream");
			is = socket.getInputStream();
			
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			byte[] bt = new byte[256];
			int n = -1;
			//当客户端关闭其输出流时,read会返回-1
			while((n = is.read(bt)) != -1) {
				baos.write(bt, 0, n);
			}
			System.out.println("message:" + new String(baos.toByteArray(), "UTF-8"));
			
			//关闭输入
			socket.shutdownInput();
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(null != socket) {
					socket.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			System.out.println("finished...");
		}
	}
}

这样一个简单的并能实现双向通信的客户端和服务端就完成了。

在上面的这里实例中,服务端通过一个while循环来处理客户段发送的请求,但是在实际中,服务段处理请求可能会需要一定的时间,这样在前一个请求未处理完成时,服务端无法处理其它的请求,因此可以通过配置一个线程池来对每次调用accept获取的Socket生成一个线程来处理请求。

注:在运行代码时,必须先启动服务端代码,否则启动客户端会找不到对应的服务端而抛出java.net.ConnectException: Connection refused: connect的异常。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值