Java中Socket编程

Java Socket编程

       对于Java Socket编程而言,有两个概念,一个是ServerSocket,一个是Socket。服务端和客户端之间通过Socket建立连接,之后它们就可以进行通信了。首先ServerSocket将在服务端监听某个端口,当发现客户端有Socket来试图连接它时,它会acceptSocket的连接请求,同时在服务端建立一个对应的Socket与之进行通信。这样就有两个Socket了,客户端和服务端各一个。

       对于Socket之间的通信其实很简单,服务端往Socket的输出流里面写东西,客户端就可以通过Socket的输入流读取对应的内容。SocketSocket之间是双向连通的,所以客户端也可以往对应的Socket输出流里面写东西,然后服务端对应的Socket的输入流就可以读出对应的内容。下面来看一些服务端与客户端通信的例子:

1.客户端写服务端读。

服务端代码

 

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		int port = 8899;
		// 定义一个ServerSocket监听在端口8899上
		ServerSocket server = new ServerSocket(port);
		// server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的
		Socket socket = server.accept();
		// 跟客户端建立好连接之后,我们就可以获取socket的InputStream,并从中读取客户端发过来的信息了。
		Reader reader = new InputStreamReader(socket.getInputStream());
		char chars[] = new char[64];
		int len;
		StringBuilder sb = new StringBuilder();
		while ((len = reader.read(chars)) != -1) {
			sb.append(new String(chars, 0, len));
		}
		System.out.println("from client: " + sb);
		reader.close();
		socket.close();
		server.close();

	}
}

服务端从SocketInputStream中读取数据的操作也是阻塞式的,如果从输入流中没有读取到数据程序会一直在那里不动,直到客户端往Socket的输出流中写入了数据,或关闭了Socket的输出流。当然,对于客户端的Socket也是同样如此。在操作完以后,整个程序结束前记得关闭对应的资源,即关闭对应的IO流和Socket

客户端代码

 

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {

	/**
	 * @param args
	 * @throws IOException 
	 * @throws UnknownHostException 
	 */
	public static void main(String[] args) throws UnknownHostException, IOException {
		String host = "127.0.0.1"; // 要连接的服务端IP地址
		int port = 8899; // 要连接的服务端对应的监听端口
		// 与服务端建立连接
		Socket client = new Socket(host, port);
		// 建立连接后就可以往服务端写数据了
		Writer writer = new OutputStreamWriter(client.getOutputStream());
		writer.write("Hello Server.");
		writer.flush();// 写完后要记得flush
		writer.close();
		client.close();
	}
}

 对于客户端往Socket的输出流里面写数据传递给服务端要注意一点,如果写操作之后程序不是对应着输出流的关闭,而是进行其他阻塞式的操作(比如从输入流里面读数据),记住要flush一下,只有这样服务端才能收到客户端发送的数据,否则可能会引起两边无限的互相等待。另外前面已经说了Socket之间是双向通信的,它既可以接收数据,同时也可以发送数据。

2.多客户端连接到一个服务器

    服务端接收一个客户端的请求之后就结束了,不能再接收其他客户端的请求了,这往往是不能满足我们的要求的。下面我们结合多线程,让一个服务器同时接收多个客户端信息,同时输出信息到客户端。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
	     int port = 8899;  
	     //定义一个ServerSocket监听在端口8899上  
	     ServerSocket server = new ServerSocket(port);  
	     while (true) {  
	         //server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的  
	         Socket socket = server.accept();  
	         //每接收到一个Socket就建立一个新的线程来处理它  
	         new Thread(new Task(socket)).start();  
	     } 
	}
}

class Task implements Runnable{
	private Socket socket;
	public Task(Socket socket) {
		this.socket = socket;  
	}
	@Override
	public void run() {
		handleSocket();  
	}
	private void handleSocket(){
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"GBK"));
			StringBuilder sb = new StringBuilder();  
			String temp;  
	        int index;  
	        while ((temp=br.readLine()) != null) {  
	            //System.out.println(temp);  
	            if ((index = temp.indexOf("eof")) != -1) {//遇到eof时就结束接收  
	            	sb.append(temp.substring(0, index));  
	                break;  
	            }  
	            sb.append(temp);  
	        }  
	        String str = sb.toString();
	        String name =  str.substring(str.indexOf("[")+1,str.indexOf("]"));
	        String content = str.substring(str.indexOf("]")+1,str.length());
	        System.out.println("from client["+name+"]:" + content);  

	         //读完后写一句  
	         Writer writer = new OutputStreamWriter(socket.getOutputStream(),"UTF-8");
	         writer.write("你好,"+name);
	         writer.write("eof\n");  
	         writer.flush();  
	         writer.close();  
	         br.close();  
	         socket.close();  
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
	}
}

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

public class Client {
	/**
	 * @param args
	 * @throws IOException 
	 * @throws UnknownHostException 
	 */
	public static void main(String[] args){
		String[] names = {"小红","小明","小黄","小兰","jeck","mako"};
		for(int i=0;i<names.length;i++){
			createClient(names[i]);
		}
	}
	
	public static void createClient(String name){
		String host = "127.0.0.1";  //要连接的服务端IP地址
		int port = 8899;   //要连接的服务端对应的监听端口
		//与服务端建立连接
		Socket client;
		try {
			client = new Socket(host, port);
			//建立连接后就可以往服务端写数据了,这里用GBK写入,服务器也要用GBK接收,否则会中文乱码
			Writer writer = new OutputStreamWriter(client.getOutputStream(), "GBK");
			writer.write("["+name+"]");
			writer.write("你好,服务端");
			writer.write("eof\n");
			writer.flush();

		
			//写完以后进行读操作,这里用UTF-8读取,服务器也要用UTF-8写,否则会中文乱码
			BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
			//设置超时间为10秒,设置接收数据的超时时间,单位是毫秒。当设置的超时时间大于0,并且超过了这一时间Socket还没有接收到返回的数据的话,Socket就会抛出一个SocketTimeoutException。
		    client.setSoTimeout(10*1000);
			StringBuffer sb = new StringBuffer();
			String temp;
			int index;
			try {  
				while ((temp=br.readLine()) != null) {
					if ((index = temp.indexOf("eof")) != -1) {
			            sb.append(temp.substring(0, index));
			            break;
			         }
			         sb.append(temp);
			     }
			} catch (SocketTimeoutException e) {
		        System.out.println("read the date time out。");  
		    } 	
			System.out.println("from server: " + sb);
			writer.close();
			br.close();
			client.close();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

 

 

 

猜你喜欢

转载自liny1224.iteye.com/blog/2282525