使用Java进行网络编程,通常会用到TCP,UDP协议。TCP是面向连接的,是可靠的传输层协议;UDP是无连接的,但是效率更高。下面是一个简单的使用Socket写的一个小例子用来实现TCP协议通信。

Server.java

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

/**
 * @description:服务器端
 * @date:(2015-9-13 下午8:41:06)
 * @author Administrator
 * @version v1.0
 * @since v1.0
 *
 * Modified history
 *
 *    Modified date:  
 *    Modifier user:     
 *    description: 
 *
 * */
public class Server {
	
	public static void main(String[] args) throws IOException, InterruptedException {
		
		//监听端口
		int port=8090;
		//服务器端监听8090端口
		ServerSocket serverSocket=new ServerSocket(port);
		//服务器端监听客户端的连接请求,accept方法是阻塞式的
		Socket socket=serverSocket.accept();
		/**
		 * 服务端从Socket的InputStream中读
		 * 取数据的操作也是阻塞式的,如果从输入
		 * 流中没有读取到数据程序会一直在那
		 * 里不动,直到客户端往Socket的输出流中写入了数据,或关闭了Socket的输出流。
		 * 客户端的Socket也是同样如此
		 * */
		BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
		StringBuffer sb=new StringBuffer();
		String temp=null;
		int index;
		while((temp=reader.readLine())!=null){
			//不设置结束符,可能输入流会
            if ((index = temp.indexOf("eof")) != -1) {//遇到eof时就结束接收  
            	sb.append(temp.substring(0, index));  
                break;  
            }
            sb.append(temp);
		}
		System.out.println("receive from client:"+sb.toString());
		//输出信息到客户端
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"));
		//读取控制台输入
		BufferedReader bufReader=new BufferedReader(new InputStreamReader(System.in));
		System.out.println("server say:");
		writer.write(bufReader.readLine());
		writer.write("hello client");
		/**
		 * BufferedReader的readLine方法是一次读一行的,
		 * 这个方法是阻塞的,直到它读到了一行数据为止程序才会继续往下执行,
		 * 那么readLine什么时候才会读到一行呢?直到程序遇到了换行符或者是对应流的
		 * 结束符readLine方法才会认为读到了一行,才会结束其阻塞,让程序继续往下执行。
		 * 所以我们在使用BufferedReader的readLine读取数据的时候一定要记得在对应的输出流里面一定要写入换行符
		 * */
		writer.write("eof\n");//设置结束符
		writer.flush();
		writer.close();
		bufReader.close();
		reader.close();
		socket.close();
		serverSocket.close();
		
	}

}



Client.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

/**
 * @description:客户端
 * @date:(2015-9-13 下午8:48:49)
 * @author Administrator
 * @version v1.0
 * @since v1.0
 *
 * Modified history
 *
 *    Modified date:  
 *    Modifier user:     
 *    description: 
 *
 * */
public class Client {
	
	public static void main(String[] args) throws IOException {
		//要连接的服务器IP地址
		String host="127.0.0.1";
		//要连接的服务器监听端口
		int port=8090;
		//与服务器端简历连接
		Socket client=new Socket(host,port);
		//设置超时间为20秒 ,
	    client.setSoTimeout(20*1000);  
		//往服务端写数据
		BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(client.getOutputStream(),"UTF-8"));
		//读取控制台
		BufferedReader bufReader=new BufferedReader(new InputStreamReader(System.in));
		System.out.println("client say:");
		writer.write(bufReader.readLine());
		writer.write("hello server");
		writer.write("eof\n");//设置结束符
		writer.flush();
		
		//接收服务端响应,socket从输入流中读取数据是一个阻塞式操作,读取不到数据会一直阻塞
		BufferedReader reader=new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));
		StringBuffer sb=new StringBuffer();
		String tmp=null;
		int index;
		while((tmp=reader.readLine())!=null){
            if ((index = tmp.indexOf("eof")) != -1) {//遇到eof时就结束接收 
            	sb.append(tmp.substring(0, index));  
                break;  
            } 
            sb.append(tmp);
		}
		System.out.println("receive from server:"+sb.toString());
		
		reader.close();
		writer.close();
		//Test
		bufReader.close();
		//Test
		client.close();
	}

}

说明:

1、服务器的ServerSocket的accept方法是用来监听端口,当监听到客户端的socket连接请求是就会创建一个Socket;accept方法是阻塞式的,如果一直没有监听到客户端Socket连接请求,它会一直阻塞下去。

2、Socket的getInputStream()方法也是阻塞式的,客户端的Socket向服务端写入数据后,假如调用getInputStream()方法想要获取服务器端的输出,它会一直阻塞,知道服务器端写入数据或者流关闭。

3、写入”eof“,用来作为结束符,防止流一直阻塞。另外,BufferedReader的readerLine方法也是阻塞式的,知道读取到一行位置,所以写入的时候记得写入换行符。