使用Socket编写Client-Server通信总结

来源:互联网 发布:淘宝潮流社区怎么申请 编辑:程序博客网 时间:2024/05/21 15:20
Socket通信是基于TCP/IP协议的一种进程间通信方式, 通过指定IP地址和端口号进行客户端与服务器的连接完成通信,使用Socket编程时的步骤如下:
服务器端:
第1步.实例化监听套接字,并指定端口号:
//一台服务器默认端口号有256*256,其中1~1023是公认端口号,1024~65535可以自定义作用;ServerSocket server = new ServerSocket(9999);
第2步.调用accept()等待客户端连接,如果没有客户端进行连接,此方法一直处于阻塞状态,直到有客户端连接,接触阻塞并返回套接字:
Socket socket = server.accept();
第3步. 使用流进根据套接字得到输入输出流进行通信:
InputStream is = socket.getInputStream();OutputStream os = socket.getOutputStream();
第4步.关闭套接字、流资源:
socket.close;is.close();os.close();
客户端:
第1步.实例化套接字,并指定服务器地址和端口:
Socket socket = new Socket("127.0.0.1",9999);
第2步.使用流进根据套接字得到输入输出流进行通信:
InputStream is = socket.getInputStream();OutputStream os = socket.getOutputStream();
第3步. 关闭套接字、流资源:
socket.close;is.close();os.close();
其中难点就在使用流进行传输,当我使用缓冲流BufferedReader和BufferedWriter时,代码如下:
//客户端中向服务器写入数据的流            writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));//服务器中读取客户端数据的流reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));while((content=reader.readLine())!=null){                if(content.equals("over")){                    System.out.println(hostName+"已下线!");                    break;                }                StringBuffer buffer = new StringBuffer(content);                writer.println(buffer.reverse().toString());                System.out.println(hostName+"说:"+content);            }
此时readLine()一直处于阻塞状态,读取不到数据,这是因为readLine()用于读取一行数据,通过换行符来判断,在一般操作中通过控制台输入数据,是可以读取到的,但是在Socket中没有提供换行符,因此一直处于阻塞状态。
解决办法:
第一种:通过BufferedWriter的newLine()写入一个分隔符,之后采用flush()刷新:
writer.write(String);writer.newLine();writer.flush();
第二种:采用打印流PrintWriter代替BufferedWriter,不过要注意,PrinterWriter刷新缓冲区的操作,如下:
//实例化PrintWriter实例,true表示启用了自动刷新,但只有调用println()、format()、printf()时才能自动刷新writer = new PrintWriter(socket.getOutputStream(),true);writer.println(String);
下面是用Socket编程实现多人聊天代码:
客户端:
import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;public class Server {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubSocket socket =null;try {//1.实例化监听套接字ServerSocket server = new ServerSocket(1994);/** * 根据监听套接字获取套接字,当每有一个客户端连接服务器时,开启一个子线程进行通讯, * 将通讯交给子线程完成 */while(true){socket = server.accept();new Thread(new Service(socket)).start();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
子线程中处理通讯的类:
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;public class Service implements Runnable{private Socket socket;private String hostName;private BufferedReader reader;private PrintWriter writer;public Service(Socket socket) {super();this.socket = socket;//通过socket获取客户端主机名hostName = socket.getInetAddress().getHostName();try {//读取客户端消息reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));//给客户端发送消息writer = new PrintWriter(socket.getOutputStream(),true);System.out.println(hostName+"已上线!");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void run() {// TODO Auto-generated method stubString content = null;try {while((content=reader.readLine())!=null){if(content.equals("over")){System.out.println(hostName+"已下线!");break;}StringBuffer buffer = new StringBuffer(content);writer.println(buffer.reverse().toString());System.out.println(hostName+"说:"+content);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{try {if(reader != null){reader.close();reader = null;}if(socket != null){socket.close();socket = null;}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
客户端:
import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;public class Client {/** * @param args */private static BufferedWriter writer;private static BufferedReader reader_keyboard,readr_fromServer;public static void main(String[] args) {// TODO Auto-generated method stubSocket socket = null;try {//1.实例化套接字,并指定主机地址和端口号 socket = new Socket(InetAddress.getLocalHost(), 1994);//向服务器写入数据的流writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));//接收从键盘输入的数据reader_keyboard = new BufferedReader(new InputStreamReader(System.in));readr_fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));String content = null;String contentFromServer = null;do{System.out.println("请输入信息:");content = reader_keyboard.readLine();if(content.equals("over")){break;}writer.write(content);writer.newLine();writer.flush();contentFromServer = readr_fromServer.readLine();if(contentFromServer!=null){System.out.println("服务器:"+contentFromServer);}}while(true);} catch (UnknownHostException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{try {if(reader_keyboard != null){reader_keyboard.close();reader_keyboard = null;}if(socket != null){socket.close();socket = null;}if(writer != null){writer.close();writer = null;}} catch (IOException e) {// TODO: handle exception}}}}







0 0