`
nanjingjiangbiao_T
  • 浏览: 2602823 次
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

Java Socket基础

 
阅读更多
Java Socket基础
较基础的Java Socket通信样例!
一、长连接通信
客户端和服务端建立通道后,Socket一直开着。两端通过read()等待消息。
1)简易聊天
服务端可主动对各个客户端发送消息,而各客户端只能单独发送给服务端。当然,只要你愿意,在服务端改下,即可转发了。
附件解压工程ChatSocket,运行TestServer、TestClient即可。src下还有两批处理,详细看TestServer文件内注释了。
1.1)ChatServer.java
  1. /**
  2. *长连接、1对n主动发消息的服务器
  3. *
  4. *@authorJoin
  5. */
  6. publicclassChatServerextendsThread{
  7. /**服务端口*/
  8. privateintport;
  9. /**服务套接字*/
  10. privateServerSocketmServerSocket;
  11. /**线程池*/
  12. privateExecutorServicepool;
  13. /**客户端套接字集合*/
  14. privateArrayList<Socket>mClientList;
  15. publicChatServer(intport){
  16. this.port=port;
  17. pool=Executors.newCachedThreadPool();//缓存线程池
  18. mClientList=newArrayList<Socket>();
  19. }
  20. @Override
  21. publicvoidrun(){
  22. try{
  23. mServerSocket=newServerSocket(port);//创建本地特定端口服务器套接字
  24. Socketclient=null;
  25. while(true){
  26. client=mServerSocket.accept();//接收连接的套接字
  27. mClientList.add(client);//加入客户端列表
  28. System.out.println(client.getInetAddress()+"建立了连接");
  29. pool.execute(newThreadServer(client));//新线程执行任务
  30. }
  31. }catch(BindExceptione){//端口使用中
  32. System.out.println("端口使用中,请关闭后重开!");
  33. }catch(IOExceptione){
  34. e.printStackTrace();
  35. }
  36. }
  37. /**各个连接客户端的服务线程*/
  38. privateclassThreadServerextendsThread{
  39. privateSocketclient;
  40. publicThreadServer(Socketclient){
  41. this.client=client;
  42. }
  43. @Override
  44. publicvoidrun(){
  45. DataInputStreamin=null;
  46. DataOutputStreamout=null;
  47. try{
  48. in=newDataInputStream(client.getInputStream());
  49. out=newDataOutputStream(client.getOutputStream());
  50. BufferedReaderwt=newBufferedReader(newInputStreamReader(
  51. System.in));//控制台输入流
  52. while(true){
  53. if(in.available()>0){
  54. /*有数据时接收*/
  55. Stringstr=in.readUTF();
  56. System.out.println(str);
  57. /*接收end或空时,退出*/
  58. if(null==str||"end".equals(str)){
  59. System.out
  60. .println(client.getInetAddress()+"正常退出");
  61. break;
  62. }
  63. /*回复或转发已接收数据*/
  64. }else{
  65. if(wt.ready()){
  66. /*控制台有数据时发送*/
  67. Stringstr=wt.readLine();
  68. sendMessage(str);//群发消息
  69. }else{
  70. try{
  71. /*发送紧急数据,判断连接*/
  72. client.sendUrgentData(0xFF);
  73. Thread.sleep(100);
  74. }catch(Exceptione){
  75. System.out.println(client.getInetAddress()
  76. +"断开连接");
  77. break;
  78. }
  79. }
  80. }
  81. }
  82. }catch(SocketExceptione){//Connectionreset
  83. System.out.println(client.getInetAddress()+"异常退出");
  84. }catch(IOExceptione){
  85. e.printStackTrace();
  86. }finally{
  87. mClientList.remove(client);//移除当前客户端
  88. try{
  89. if(null!=in){
  90. in.close();
  91. }
  92. if(null!=out){
  93. out.close();
  94. }
  95. if(null!=client){
  96. client.close();
  97. }
  98. }catch(IOExceptione){
  99. e.printStackTrace();
  100. }
  101. }
  102. }
  103. }
  104. /**
  105. *群发信息
  106. *@throwsIOException
  107. */
  108. publicvoidsendMessage(Stringmsg)throwsIOException{
  109. DataOutputStreamout=null;
  110. for(Socketclient:mClientList){
  111. out=newDataOutputStream(client.getOutputStream());
  112. out.writeUTF(msg);
  113. out.flush();
  114. }
  115. }
  116. }
1.2)ChatClient.java
  1. /**
  2. *接收和发送消息的客户端
  3. *
  4. *@authorJoin
  5. */
  6. publicclassChatClientextendsThread{
  7. /**套接字地址*/
  8. privateSocketAddressaddress;
  9. /**超时时间*/
  10. privateinttimeout;
  11. publicChatClient(Stringhost,intport,inttimeout){
  12. this.address=newInetSocketAddress(host,port);
  13. this.timeout=timeout;
  14. }
  15. @Override
  16. publicvoidrun(){
  17. Socketsocket=newSocket();//创建未连接套接字
  18. try{
  19. //socket.setOOBInline(false);//默认即是false,表示不处理紧急数据
  20. socket.connect(address,timeout);//连接到服务器,并指定超时时间
  21. handleSocket(socket);//数据接收发送处理
  22. }catch(ConnectExceptione){//拒绝连接
  23. System.out.println("连接不上服务器");
  24. }catch(SocketTimeoutExceptione){//连接超时
  25. System.out.println("连接服务器超时");
  26. }catch(IOExceptione){
  27. e.printStackTrace();
  28. }finally{
  29. try{
  30. if(null!=socket){
  31. socket.close();//关闭Socket
  32. }
  33. }catch(IOExceptione){
  34. e.printStackTrace();
  35. }
  36. }
  37. }
  38. privatevoidhandleSocket(Socketsocket){
  39. DataInputStreamin=null;
  40. DataOutputStreamout=null;
  41. try{
  42. in=newDataInputStream(socket.getInputStream());
  43. out=newDataOutputStream(socket.getOutputStream());
  44. BufferedReaderwt=newBufferedReader(newInputStreamReader(
  45. System.in));//控制台输入流
  46. while(true){
  47. if(wt.ready()){
  48. /*控制台有数据时发送*/
  49. Stringstr=wt.readLine();
  50. out.writeUTF(str);
  51. out.flush();
  52. /*发送end时,自身也退出*/
  53. if(str.equals("end")){
  54. break;
  55. }
  56. }else{
  57. try{
  58. /*发送紧急数据,判断连接*/
  59. socket.sendUrgentData(0xFF);
  60. Thread.sleep(100);
  61. }catch(Exceptione){
  62. System.out.println("服务器断开连接");
  63. break;
  64. }
  65. }
  66. /*有数据时接收并输出*/
  67. if(in.available()>0)
  68. System.out.println(in.readUTF());
  69. }
  70. }catch(SocketExceptione){//Connectionreset
  71. System.out.println("服务器异常");
  72. }catch(IOExceptione){
  73. e.printStackTrace();
  74. }finally{
  75. try{
  76. if(null!=in){
  77. in.close();
  78. }
  79. if(null!=out){
  80. out.close();
  81. }
  82. }catch(IOExceptione){
  83. e.printStackTrace();
  84. }
  85. }
  86. }
  87. }

2)对象消息

发送对象消息。服务端有LinkServer和LinkServer2两个,分别支持单客户端与多客户端,方式也有些不一样。
附件解压工程LinkedSocketB,.test包内Test开头的即是测试类了。服务端接收到客户端连接时,直接一个循环发送n个对象过去,没什么大问题^^。
2.1)LinkClient.java
  1. /**
  2. *只建立一个Socket,长连接Server接收数据。
  3. *
  4. *@authorJoin
  5. */
  6. publicclassLinkClientextendsThread{
  7. /**套接字地址*/
  8. privateSocketAddressaddress;
  9. /**超时时间*/
  10. privateinttimeout;
  11. /**客户端监听接口*/
  12. privateOnLinkClientListenerlistener;
  13. /**
  14. *构造客户端
  15. *
  16. *@paramhost服务器名称
  17. *@paramport服务器端口
  18. *@paramtimeout连接超时时间
  19. */
  20. publicLinkClient(Stringhost,intport,inttimeout){
  21. this.address=newInetSocketAddress(host,port);
  22. this.timeout=timeout;
  23. }
  24. @Override
  25. publicvoidrun(){
  26. Socketsocket=newSocket();//创建未连接套接字
  27. try{
  28. socket.connect(address,timeout);//连接到服务器,并指定超时时间
  29. if(null!=listener){
  30. listener.onConnected();
  31. }
  32. receiveObj(socket);//接收服务器数据
  33. }catch(ConnectExceptione){//拒绝连接
  34. if(null!=listener){
  35. listener.onConnectException();
  36. }
  37. }catch(SocketTimeoutExceptione){//连接超时
  38. if(null!=listener){
  39. listener.onTimeoutException();
  40. }
  41. }catch(IOExceptione){
  42. e.printStackTrace();
  43. }finally{
  44. try{
  45. if(null!=socket){
  46. socket.close();//关闭Socket
  47. }
  48. }catch(IOExceptione){
  49. e.printStackTrace();
  50. }
  51. }
  52. }
  53. /**接收服务器发送的对象*/
  54. privatevoidreceiveObj(Socketsocket){
  55. //socket.shutdownOutput();//半关闭输出流
  56. ObjectInputStreamis=null;
  57. try{
  58. is=newObjectInputStream(newBufferedInputStream(
  59. socket.getInputStream()));
  60. /**循环接收对象*/
  61. while(true){
  62. Objectobj=is.readObject();
  63. if(null==obj){
  64. break;
  65. }
  66. if(null!=listener){
  67. listener.onReceive(obj);
  68. }
  69. }
  70. if(null!=listener){
  71. listener.onExited();
  72. }
  73. }catch(SocketExceptione){//Connectionreset
  74. if(null!=listener){
  75. listener.onSocketException();
  76. }
  77. }catch(IOExceptione){
  78. e.printStackTrace();
  79. }catch(ClassNotFoundExceptione){
  80. e.printStackTrace();
  81. }finally{
  82. try{
  83. if(null!=is){
  84. is.close();
  85. }
  86. if(null!=socket){
  87. socket.close();
  88. }
  89. }catch(IOExceptione){
  90. e.printStackTrace();
  91. }
  92. }
  93. }
  94. /**设置客户端监听接口*/
  95. publicvoidsetOnLinkClientListener(OnLinkClientListenerlistener){
  96. this.listener=listener;
  97. }
  98. }
2.2)LinkServer.java
  1. /**
  2. *开启服务器,长连接一个Socket,主动发送数据
  3. *
  4. *@authorJoin
  5. */
  6. publicclassLinkServerextendsThread{
  7. /**服务端口*/
  8. privateintport;
  9. /**服务套接字*/
  10. privateServerSocketmServerSocket;
  11. /**线程池*/
  12. privateExecutorServicepool;
  13. /**服务器监听接口*/
  14. privateOnLinkServerListenerlistener;
  15. /**同步对象*/
  16. privateObjectlockObj=newObject();
  17. /**是否等待*/
  18. privatebooleanisWaiting=false;
  19. /**发送对象集合*/
  20. privateArrayList<Object>sendObjList;
  21. publicLinkServer(intport){
  22. this.port=port;
  23. pool=Executors.newCachedThreadPool();//缓存线程池
  24. sendObjList=newArrayList<Object>();
  25. }
  26. @Override
  27. publicvoidrun(){
  28. try{
  29. mServerSocket=newServerSocket(port);//创建本地特定端口服务器套接字
  30. Socketclient=null;
  31. client=mServerSocket.accept();//接收连接的套接字
  32. if(null!=listener){
  33. listener.onClientConnected(client.getInetAddress());
  34. }
  35. pool.execute(newThreadServer(client));//新线程执行任务
  36. }catch(BindExceptione){//端口使用中
  37. if(null!=listener){
  38. listener.onBindException();
  39. }
  40. }catch(IOExceptione){
  41. e.printStackTrace();
  42. }
  43. }
  44. /**各个连接客户端的服务线程*/
  45. privateclassThreadServerextendsThread{
  46. privateSocketclient;
  47. publicThreadServer(Socketclient){
  48. this.client=client;
  49. }
  50. @Override
  51. publicvoidrun(){
  52. ObjectOutputStreamos=null;
  53. try{
  54. os=newObjectOutputStream(client.getOutputStream());
  55. ObjectsendObj;
  56. synchronized(lockObj){
  57. while(true){
  58. if(sendObjList.size()<=0){
  59. isWaiting=true;
  60. lockObj.wait();
  61. }
  62. sendObj=sendObjList.get(0);
  63. os.writeObject(sendObj);
  64. os.flush();
  65. /*发送null时,表示退出了*/
  66. if(null==sendObj){
  67. if(null!=listener){
  68. listener.onExited(client.getInetAddress());
  69. }
  70. break;
  71. }
  72. sendObjList.remove(0);
  73. }
  74. }
  75. }catch(SocketExceptione){//Connectionreset
  76. if(null!=listener){
  77. listener.onSocketException(client.getInetAddress());
  78. }
  79. }catch(IOExceptione){
  80. e.printStackTrace();
  81. }catch(InterruptedExceptione){
  82. e.printStackTrace();
  83. }finally{
  84. try{
  85. if(null!=os){
  86. os.close();
  87. }
  88. if(null!=client){
  89. client.close();
  90. }
  91. }catch(IOExceptione){
  92. e.printStackTrace();
  93. }
  94. }
  95. }
  96. }
  97. /**发送序列化对象*/
  98. publicvoidsendObj(Objectobj){
  99. /*这个判断非必需的,记得就好*/
  100. if(null!=obj&&!isSerializable(obj))
  101. thrownewIllegalArgumentException(
  102. "Objectneedstoimplementjava.io.Serializable!");
  103. sendObjList.add(obj);
  104. if(isWaiting){
  105. synchronized(lockObj){
  106. lockObj.notifyAll();
  107. }
  108. isWaiting=false;
  109. }
  110. }
  111. /**判断是否序列化*/
  112. privatebooleanisSerializable(Objectobj){
  113. Class<?>[]cls=obj.getClass().getInterfaces();
  114. for(Class<?>clazz:cls){
  115. if(clazz.getName().equals(Serializable.class.getName()))
  116. returntrue;
  117. }
  118. returnfalse;
  119. }
  120. /**设置服务器监听接口*/
  121. publicvoidsetOnLinkServerListener(OnLinkServerListenerlistener){
  122. this.listener=listener;
  123. }
  124. }
                                2.3)LinkServer2.java
                                1. /**
                                2. *开启服务器,长连接各个Socket,主动发送数据
                                3. *
                                4. *@authorJoin
                                5. */
                                6. publicclassLinkServer2extendsThread{
                                7. /**服务端口*/
                                8. privateintport;
                                9. /**服务套接字*/
                                10. privateServerSocketmServerSocket;
                                11. /**服务器监听接口*/
                                12. privateOnLinkServerListenerlistener;
                                13. /**客户端套接字集合*/
                                14. privateArrayList<Socket>clientList;
                                15. /**客户端的输出流集合*/
                                16. privateArrayList<ObjectOutputStream>osList;
                                17. publicLinkServer2(intport){
                                18. this.port=port;
                                19. clientList=newArrayList<Socket>();
                                20. osList=newArrayList<ObjectOutputStream>();
                                21. }
                                22. @Override
                                23. publicvoidrun(){
                                24. try{
                                25. mServerSocket=newServerSocket(port);//创建本地特定端口服务器套接字
                                26. Socketclient=null;
                                27. while(true){
                                28. client=mServerSocket.accept();//接收连接的套接字
                                29. if(null!=listener){
                                30. listener.onClientConnected(client.getInetAddress());
                                31. }
                                32. clientList.add(client);
                                33. osList.add(newObjectOutputStream(client.getOutputStream()));//增加连接的输出流
                                34. }
                                35. }catch(BindExceptione){//端口使用中
                                36. if(null!=listener){
                                37. listener.onBindException();
                                38. }
                                39. }catch(IOExceptione){
                                40. e.printStackTrace();
                                41. }
                                42. }
                                43. /**发送序列化对象*/
                                44. publicvoidsendObj(Objectobj){
                                45. /*这个判断非必需的,记得就好*/
                                46. if(null!=obj&&!isSerializable(obj))
                                47. thrownewIllegalArgumentException(
                                48. "Objectneedstoimplementjava.io.Serializable!");
                                49. ObjectOutputStreamout=null;
                                50. for(inti=0;i<osList.size();i++){
                                51. try{
                                52. out=osList.get(i);
                                53. out.writeObject(obj);
                                54. out.flush();
                                55. /*发送null时,表示退出了*/
                                56. if(null==obj){
                                57. if(null!=listener){
                                58. listener.onExited(clientList.get(i).getInetAddress());
                                59. }
                                60. closeSocket(i);//关闭当前Socket
                                61. i--;//少了个记得减
                                62. }
                                63. }catch(SocketExceptione){//Connectionreset
                                64. if(null!=listener){
                                65. listener.onSocketException(clientList.get(i)
                                66. .getInetAddress());
                                67. }
                                68. closeSocket(i);//关闭当前Socket
                                69. i--;//少了个记得减
                                70. }catch(IOExceptione){
                                71. e.printStackTrace();
                                72. closeSocket(i);//关闭当前Socket
                                73. i--;//少了个记得减
                                74. }
                                75. }
                                76. }
                                77. /**关闭某个Socket*/
                                78. privatevoidcloseSocket(intindex){
                                79. try{
                                80. osList.get(index).close();
                                81. osList.remove(index);
                                82. clientList.get(index).close();
                                83. clientList.remove(index);
                                84. }catch(IOExceptione1){
                                85. e1.printStackTrace();
                                86. }
                                87. }
                                88. /**判断是否序列化*/
                                89. privatebooleanisSerializable(Objectobj){
                                90. Class<?>[]cls=obj.getClass().getInterfaces();
                                91. for(Class<?>clazz:cls){
                                92. if(clazz.getName().equals(Serializable.class.getName()))
                                93. returntrue;
                                94. }
                                95. returnfalse;
                                96. }
                                97. /**设置服务器监听接口*/
                                98. publicvoidsetOnLinkServerListener(OnLinkServerListenerlistener){
                                99. this.listener=listener;
                                100. }
                                101. }
                                二、短连接通信
                                客户端请求一次,建立一次Socket,完成后即可关闭。服务端通过accept()等待。
                                1)对象消息
                                客户端发送对象,服务端接受对象,很简单的例子。
                                1.1)EasyClient.java
                                1. /**
                                2. *每次连接服务器发送一个消息
                                3. *
                                4. *@authorJoin
                                5. */
                                6. publicclassEasyClient{
                                7. /**套接字地址*/
                                8. privateSocketAddressaddress;
                                9. /**超时时间*/
                                10. privateinttimeout;
                                11. /**客户端监听接口*/
                                12. privateOnClientListenerlistener;
                                13. publicEasyClient(Stringhost,intport,inttimeout){
                                14. this.address=newInetSocketAddress(host,port);
                                15. this.timeout=timeout;
                                16. }
                                17. /**
                                18. *发送一个消息
                                19. *
                                20. *@paramobj对象消息
                                21. */
                                22. publicbooleansendMessage(Objectobj){
                                23. booleanresult=false;
                                24. Socketsocket=null;
                                25. try{
                                26. socket=newSocket();
                                27. socket.connect(address,timeout);
                                28. if(null!=listener){
                                29. listener.onConnected();
                                30. }
                                31. result=sendMessage(socket,obj);
                                32. }catch(ConnectExceptione){//拒绝连接
                                33. if(null!=listener){
                                34. listener.onConnectException();
                                35. }
                                36. }catch(SocketTimeoutExceptione){//连接超时
                                37. if(null!=listener){
                                38. listener.onTimeoutException();
                                39. }
                                40. }catch(IOExceptione){
                                41. e.printStackTrace();
                                42. }finally{
                                43. try{
                                44. if(null!=socket){
                                45. socket.close();//关闭Socket
                                46. socket=null;
                                47. }
                                48. }catch(IOExceptione){
                                49. e.printStackTrace();
                                50. }
                                51. }
                                52. returnresult;
                                53. }
                                54. /**通过Socket发送obj消息*/
                                55. privatebooleansendMessage(Socketsocket,Objectobj){
                                56. booleanresult=false;
                                57. ObjectOutputStreamos=null;
                                58. try{
                                59. os=newObjectOutputStream(socket.getOutputStream());
                                60. os.writeObject(obj);
                                61. os.flush();
                                62. if(null!=listener){
                                63. listener.onMessageSent(obj);
                                64. }
                                65. result=true;
                                66. }catch(SocketExceptione){//Connectionreset
                                67. if(null!=listener){
                                68. listener.onSocketException();
                                69. }
                                70. }catch(IOExceptione){
                                71. e.printStackTrace();
                                72. }finally{
                                73. try{
                                74. if(null!=os){
                                75. os.close();
                                76. }
                                77. }catch(IOExceptione){
                                78. e.printStackTrace();
                                79. }
                                80. }
                                81. returnresult;
                                82. }
                                83. /**设置客户端监听接口*/
                                84. publicvoidsetOnClientListener(OnClientListenerlistener){
                                85. this.listener=listener;
                                86. }
                                87. }
                                1.2)EasyServer.java
                                1. publicclassEasyServerextendsThread{
                                2. /**服务端口*/
                                3. privateintport;
                                4. /**服务套接字*/
                                5. privateServerSocketmServerSocket;
                                6. /**服务器监听接口*/
                                7. privateOnServerListenerlistener;
                                8. publicEasyServer(intport){
                                9. this.port=port;
                                10. }
                                11. @Override
                                12. publicvoidrun(){
                                13. try{
                                14. mServerSocket=newServerSocket(port);//创建本地特定端口服务器套接字
                                15. Socketsocket=null;
                                16. while(true){
                                17. socket=mServerSocket.accept();//接收连接的套接字
                                18. receiveMessage(socket);//接收socket处理消息
                                19. }
                                20. }catch(BindExceptione){//端口使用中
                                21. if(null!=listener){
                                22. listener.onBindException();
                                23. }
                                24. }catch(IOExceptione){
                                25. e.printStackTrace();
                                26. }
                                27. }
                                28. /**接收处理每个Socket信息*/
                                29. privatevoidreceiveMessage(Socketsocket){
                                30. ObjectInputStreamis=null;
                                31. try{
                                32. is=newObjectInputStream(newBufferedInputStream(
                                33. socket.getInputStream()));
                                34. Objectobj=is.readObject();
                                35. if(null!=listener){
                                36. listener.onReceive(socket.getInetAddress(),obj);
                                37. }
                                38. }catch(SocketExceptione){//Connectionreset
                                39. if(null!=listener){
                                40. listener.onSocketException(socket.getInetAddress());
                                41. }
                                42. }catch(IOExceptione){
                                43. e.printStackTrace();
                                44. }catch(ClassNotFoundExceptione){
                                45. e.printStackTrace();
                                46. }finally{
                                47. try{
                                48. if(null!=is){
                                49. is.close();
                                50. }
                                51. if(null!=socket){
                                52. socket.close();
                                53. }
                                54. }catch(IOExceptione){
                                55. e.printStackTrace();
                                56. }
                                57. }
                                58. }
                                59. /**设置服务器监听接口*/
                                60. publicvoidsetOnServerListener(OnServerListenerlistener){
                                61. this.listener=listener;
                                62. }
                                63. }
                                三、后记
                                恩,哦,socket还有个比较常用的是setSoTimeout(),在read()阻塞超时会报SocketTimeoutException,catch住处理即可。
                                更多的如SSLSocket、NIO的简单例子,可以先Click here!这个整理好的样例工程就不提供了,自己动手^^!

                                ps:老遇到8W冗余字符,拆着拆着就三个了==!

                                出处http://vaero.blog.51cto.com/4350852/893847

                                分享到:
                                评论

                                相关推荐

                                Global site tag (gtag.js) - Google Analytics