【Java】Socket套接字C/S结构简单练习
服务端Server代码:
1 package Server; 2 import java.io.*; 3 import java.net.*; 4 5 public class TServer { 6 7 public static void main(String[] args) { 8 // TODO Auto-generated method stub 9 ServerSocket serverSocket = null; 10 ServerThread serverThread ; 11 final int portNum = 39839; //使用11520发现一直是在创建serverSocket时失败 12 Socket clientSocket = null; 13 14 try { 15 serverSocket = new ServerSocket(portNum); 16 } catch (IOException e) { 17 //e.printStackTrace(); 18 System.out.println("启动服务端时,发生错误...."); 19 } 20 System.out.println("服务端已启动....\n等待客户端的连接......"); 21 22 while(true){ 23 try { 24 clientSocket = serverSocket.accept(); 25 if (clientSocket.isConnected()) 26 System.out.println("客户端IP【"+clientSocket.getInetAddress().getHostAddress()+"】连接进入..."); 27 } catch (IOException e) { 28 //e.printStackTrace(); 29 System.out.println("等待客户端呼入时,发生错误...."); 30 } 31 if (clientSocket.isConnected()) { //增加对socket连接的判断,避免因为客户端的在中途断开连接引起的线程错误 32 serverThread = new ServerThread(clientSocket); 33 serverThread.start(); 34 }else { 35 continue; 36 } 37 } 38 39 } 40 41 } 42 43 44 45 class ServerThread extends Thread{ 46 Socket socket; 47 String s = null; 48 DataOutputStream outs = null; 49 DataInputStream ins = null; 50 51 ServerThread(Socket sct){ 52 socket = sct; 53 try { 54 ins = new DataInputStream(sct.getInputStream()); 55 outs = new DataOutputStream(sct.getOutputStream()); 56 } catch (IOException e) { 57 // TODO Auto-generated catch block 58 e.printStackTrace(); 59 } 60 } 61 62 @SuppressWarnings("deprecation") 63 public void run(){ 64 while(true){ 65 try { 66 if (socket.isConnected()) 67 s = ins.readUTF(); 68 else 69 //this.destroy(); // 异常断开的连接直接清理掉。。这个处理方式不行,会导致整个线程死掉(待完善,如果意外中断的socket再次连接时,能够自动续接) 70 break; 71 } catch (IOException e) { 72 // TODO Auto-generated catch block 73 System.out.println("客户端【"+socket.getInetAddress().getHostAddress()+"】异常中断..."); 74 break; 75 } 76 77 try { 78 if (s.equals("结束")){ 79 outs.writeUTF(s); 80 socket.close(); //关闭当前客户端的连接 81 System.out.println("客户端IP【"+socket.getInetAddress().getHostAddress()+"】正常退出连接!"); 82 this.stop(); //当前线程结束 83 }else{ 84 System.out.println("客户端IP【"+socket.getInetAddress().getHostAddress()+"】发来消息:"+s); 85 outs.writeUTF("" + socket.getInetAddress().getHostName() + ",你对我说了【"+ s + "】"); 86 } 87 } catch (IOException e) { 88 // TODO Auto-generated catch block 89 System.out.println("向客户端发送信息失败..."); 90 } 91 } 92 } 93 }
客户端Client代码:
1 package Client; 2 import java.awt.event.*; 3 import java.awt.*; 4 import javax.swing.*; 5 import javax.xml.crypto.dsig.keyinfo.KeyValue; 6 7 import java.io.*; 8 import java.net.*; 9 import java.util.concurrent.TimeoutException; 10 11 public class JavaClientSocketMain { 12 13 public static void main(String[] args) { 14 // TODO Auto-generated method stub 15 TClient tcFrame = new TClient(); 16 tcFrame.setVisible(true); 17 } 18 19 } 20 21 22 class TClient extends JFrame implements ActionListener, Runnable,KeyListener { 23 JButton btSend ; JButton btRelink ; 24 JTextField textF ; JTextArea textA; 25 JScrollPane scrollPane; 26 SocketAddress socketAddr; 27 Socket socket ; Thread thread ; 28 //TimeoutThread loseConnectionThread; 29 DataInputStream ins; DataOutputStream outs; 30 final int portNum = 39839; 31 final String serverIPAddress = "192.168.1.124"; 32 33 TClient(){ 34 setBackground(new Color(120,153,137)); 35 setLayout(new BorderLayout()); 36 btSend = new JButton("发送信息"); 37 btRelink = new JButton("重新连接"); 38 textF = new JTextField(20); //限长文本框 39 textA = new JTextArea(20,30); //限长限宽文本区 40 scrollPane = new JScrollPane(textA); 41 textA.setText("正在请求连接服务端......"); 42 setSize(450,350); 43 setLocationRelativeTo(null); //窗体于屏幕居中显示 44 JPanel p = new JPanel(); 45 p.add(textF); p.add(btSend); p.add(btRelink); 46 this.add(scrollPane, "Center"); this.add(p, "South"); 47 btSend.addActionListener(this); 48 btRelink.addActionListener(this); 49 textF.addKeyListener(this); 50 51 //窗口退出按钮事件 52 this.addWindowListener(new WindowAdapter(){ 53 public void windowClosing(WindowEvent e){ 54 try { 55 socket.close(); 56 thread.stop(); 57 } catch (IOException e1) {} 58 System.exit(0); 59 } 60 }); 61 62 linkToServer(serverIPAddress , portNum); //构造器,连接到服务器 63 } 64 65 66 67 @Override 68 public void run() { 69 // 线程运行过程 70 String s = null; 71 while(true) { 72 try { 73 s = ins.readUTF(); //读取服务端放入流中的信息 74 } catch (IOException e) { 75 // TODO Auto-generated catch block 76 e.printStackTrace(); 77 return ; 78 } 79 if (s.equals("结束")){ //当服务器放入流中的信息有“结束”两字时,关闭socket连接 80 try { 81 socket.close(); 82 System.exit(0); 83 //break; 84 } catch (IOException e) { 85 // TODO Auto-generated catch block 86 e.printStackTrace(); 87 return ; 88 } 89 } 90 else 91 textA.append(s + "\n"); 92 } 93 94 } 95 96 //发送消息 97 public void sendMessage(){ 98 if (socket.isConnected()){ 99 String s = textF.getText(); 100 if (s != null){ 101 try { 102 outs.writeUTF(s); 103 } catch (IOException e) { 104 // TODO Auto-generated catch block 105 e.printStackTrace(); 106 } 107 } 108 else { 109 try { 110 outs.writeUTF("请服务端发送信息!"); 111 } catch (IOException e) { 112 // TODO Auto-generated catch block 113 e.printStackTrace(); 114 } 115 } 116 }else { 117 textA.append("\n...未连接...."); 118 } 119 textF.setText(""); 120 } 121 122 // 连接到指定的服务端 123 public boolean linkToServer(String ipAddr, int pNum){ 124 try { 125 socketAddr = new InetSocketAddress(ipAddr,pNum); 126 socket = new Socket() ; 127 socket.connect(socketAddr,1000); // 192.168.1.124作为服务端 端口4321,等待1秒钟,如果1秒钟之后还没有连接上,则抛出异常 128 129 if(socket.isConnected()){ 130 ins = new DataInputStream(socket.getInputStream()); 131 outs = new DataOutputStream(socket.getOutputStream()); 132 textA.setText("已连接到"+socket.getInetAddress().getHostAddress()+"\n"); 133 } 134 135 } catch (UnknownHostException e) { 136 //e.printStackTrace(); 137 textA.setText("找不到服务端啦...\n可能的错误信息:\n"+e.getMessage()); 138 return false; 139 } catch (IOException e) { 140 //e.printStackTrace(); 141 textA.setText("找不到服务端啦...\n可能的错误信息:\n" + e.getMessage()); 142 return false; 143 } 144 145 if (thread == null){ //建立线程 146 thread = new Thread(this); 147 thread.setPriority(Thread.MIN_PRIORITY); 148 thread.start(); //启动线程 149 return true; 150 }else return false; 151 } 152 153 @Override 154 public void actionPerformed(ActionEvent arg0) { 155 // “发送信息” 按钮功能实现 156 if (arg0.getSource() == btSend){ 157 sendMessage(); 158 } 159 160 // 重连服务端的按钮功能实现 161 if (arg0.getSource() == btRelink){ 162 linkToServer(serverIPAddress , portNum); 163 } 164 } 165 166 public void keyPressed(KeyEvent e){ 167 if (e.getKeyCode() == KeyEvent.VK_ENTER){ 168 sendMessage(); 169 } 170 } 171 @Override 172 public void keyReleased(KeyEvent arg0) {} 173 @Override 174 public void keyTyped(KeyEvent arg0) {} 175 176 }