1.網絡編程簡要概述: 網絡編程實質實質就是兩個(或多個)設備(例如計算機)之間的數據傳輸。而要實現兩臺計算機經過互聯網鏈接進行數據傳輸,必輸要知足計算機網絡的5層協議(物理層,數據鏈路層,網絡層,運輸層,應用層);固然有劃分可能不一樣,但如今你們比較容易接受理解的是五層模型。而其中前三層物理層,數據鏈路層以及網絡層,做爲java程序員暫時是不能直接對他進行控制的。html
URL基本格式:protocol://hostname:port/resourcename#anchorprotocol:使用的協議,能夠是http,ftp,news,telnet等hostname:主機名port:端口號,可選resourcename:資源名,主機上能訪問到的目錄或文件anchor:標記,可選,指定文件中的有特定標記的位置 如:http://localhost:8080/HttpSer/index.html。java
下面主要經過UDP和socket編程來說解網絡編程; 2. UDP編程介紹: 1.簡介: 2.UDP(User Datagram Protocol),中文意思是用戶數據報協議,方式相似於發短信息,是一種物美價廉的通信方式,使用該種方式無需創建專用的虛擬鏈接,因爲無需創建專用的鏈接,因此對於服務器的壓力要比TCP小不少。是一種儘量可靠傳輸的協議。主要用於視頻電話等對信息準確傳輸性不高追求速度的應用程序。 3.主要類的講解: 4.DatagramSocket: 5.DatagramSocket類實現「網絡鏈接」,包括客戶端網絡鏈接和服務器端網絡鏈接。雖然UDP方式的網絡通信不須要創建專用的網絡鏈接,可是畢竟仍是須要發送和接收數據,DatagramSocket實現的就是發送數據時的發射器,以及接收數據時的監聽器的角色 6.DatagramPacket: 7.DatagramPacket類實現對於網絡中傳輸的數據封裝,也就是說,該類的對象表明網絡中交換的數據。在UDP方式的網絡編程中,不管是須要發送的數據仍是須要接收的數據,都必須被處理成DatagramPacket類型的對象,該對象中包含發送到的地址、發送到的端口號以及發送的內容等。 8.一個簡單的udp通訊: 9.客戶端: DatagramSocket ds = null; //定義一個UDP來發送數據 ds = new DatagramSocket(); //假設發送的數據是個字符串 String hello = "hello world"; //定義一個UDP的數據發送包來發送數據,inetSocketAddress表示要接收的地址 DatagramPacket dp = new DatagramPacket(hello.getBytes() ,hello.getBytes().length,new InetSocketAddress("127.0.0.1", 9999)); for(int i=0;i<10;i++) { //數據發送 ds.send(dp); //線程睡眠1s Thread.sleep(1000); }程序員
3.socket編程介紹: 1.socket簡介: 2.Socket是TCP/IP協議的一個十分流行的編程界面,一個Socket由一個IP地址和一個端口號惟一肯定。 3.而TCP是Tranfer Control Protocol的 簡稱,是一種面向鏈接的保證可靠傳輸的協議。經過TCP協議傳輸,獲得的是一個順序的無差錯的數據流。發送方和接收方的成對的兩個socket之間必須創建鏈接,以便在TCP協議的基礎上進行通訊,當一個socket(一般都是server socket)等待創建鏈接時,另外一個socket能夠要求進行鏈接,一旦這兩個socket鏈接起來,它們就能夠進行雙向數據傳輸,雙方均可以進行發送 或接收操做。 4.主要的類介紹: 5.1.創建服務器類:ServerSocket 6.能夠用服務器須要使用的端口號做爲參數來建立服務器對象: 7.ServerSocket serverSocket = new ServerSocket(8888) 8.這條語句建立了一個服務器對象,這個服務器使用8888號端口。當一個客戶端程序創建一個Socket鏈接,所鏈接的端口號爲8888時,服務器對象server便響應這個鏈接,而且server.accept()方法會建立一個Socket對象。服務器端即可以利用這個Socket對象與客戶進行通信。 //進行監聽,當客戶端沒數據發送過來時,停在這裏; Socket s=serverSocket.accept(); 1 2 2.通訊類:Socket 服務器端和客戶端能夠經過Socket類進行通訊: 客戶端創建socket類過程: //創建socket客戶端:第一個參數:ip地址;第二個參數:發送的端口,假如沒有服務器,會停在這裏,而後扔出異常; Socket socket=new Socket("192.168.1.105", 8888); 1 2 經過socket類能夠得到輸入輸出流進行通訊: //得到socket的輸出流 PrintWriter out=new PrintWriter(socket.getOutputStream()); //得到socket的輸入流 BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream())); 簡單的socket通訊一對一 服務端: package onetoone;import java.awt.BorderLayout;import java.awt.Color;import java.awt.FlowLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyEvent;import java.io.;import java.net.;import java.util.Calendar;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;import javax.swing.border.LineBorder;import javax.swing.border.TitledBorder; public class ChatServer extends JFrame{ private static final long serialVersionUID = 1L; private static int port=8000;//默認端口編程
static DataOutputStream outToClient; static DataInputStream inputFromClient;服務器
static PrintWriter pw;網絡
ChatServer(){ //界面佈局---------------------------------------- JPanel panelTop=new JPanel(new FlowLayout()); panelTop.add(jlbHostIp); String hostIp; try { hostIp = InetAddress.getLocalHost().getHostAddress().toString();//本機IP jtfIp.setText(hostIp); } catch (UnknownHostException e) { jtfIp.setText("獲取失敗"); } jtfIp.setForeground(Color.orange); panelTop.add(jtfIp); panelTop.add(jlbOpenPort); jtfPort.setText(""+port);jtfPort.setForeground(Color.orange);panelTop.add(jtfPort); jbtStart=new JButton("啓動");jbtStart.setBackground(Color.green);panelTop.add(jbtStart); jlbIsStart=new JLabel("[還沒有啓動]");jlbIsStart.setForeground(Color.RED);panelTop.add(jlbIsStart); jbtClear=new JButton(" 清除記錄");jbtClear.setBackground(Color.YELLOW);panelTop.add(jbtClear); panelTop.setBorder(new LineBorder(Color.BLACK));socket
JPanel panel1=new JPanel(new BorderLayout()); panel1.add(jtaContent,BorderLayout.CENTER); jbtSend.setEnabled(false); jbtSend.setBackground(Color.YELLOW);jbtSend.setMnemonic(KeyEvent.VK_ENTER);panel1.add(jbtSend,BorderLayout.EAST); panel1.setBorder(new LineBorder(Color.BLACK));ide
JPanel panel2=new JPanel(new BorderLayout()); //把定義的JTextArea放到JScrollPane裏面去 JScrollPane scrollPanel = new JScrollPane(jtaChatRecord); //分別設置水平和垂直滾動條自動出現 scrollPanel.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollPanel.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);佈局
panel2.add(scrollPanel,BorderLayout.CENTER); panel2.setBorder(new TitledBorder("聊天記錄"));this
JPanel panelDown=new JPanel(new BorderLayout()); panelDown.add(panel1,BorderLayout.SOUTH); panelDown.add(panel2,BorderLayout.CENTER);
add(panelTop,BorderLayout.NORTH); add(panelDown,BorderLayout.CENTER);
setTitle("服務端"); setSize(500,390); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); //--------------------------------------------
//獲取系統當前時間 public static String getCurrentTime(){ Calendar ca = Calendar.getInstance(); int y= ca.get(Calendar.YEAR);//獲取年份 int m=ca.get(Calendar.MONTH)+1;//獲取月份 int d=ca.get(Calendar.DATE);//獲取日 int h=ca.get(Calendar.HOUR_OF_DAY);//小時 int min=ca.get(Calendar.MINUTE);//分 int s=ca.get(Calendar.SECOND);//秒 return "["+y+"/"+m+"/"+d+" "+h+":"+min+":"+s+"]"; }
//啓動發送消息的線程 public static void openSendThread(String sendMsg){ Runnable sendRun=new sendMsgToClient(sendMsg); Thread sendThread=new Thread(sendRun); sendThread.start(); }
//啓動窗口程序 public static void main(String[] args) { new ChatServer(); } } //用於接收信息的線程 class GetMsgFromClient implements Runnable{ private DataInputStream in; private JTextArea jtaChatRecord;
public GetMsgFromClient(DataInputStream in,JTextArea jtaChatRecord){ this.in=in; this.jtaChatRecord=jtaChatRecord; } @Override public void run() { try { BufferedReader br=new BufferedReader(new InputStreamReader(in)); String msg = ""; while ((msg = br.readLine()) != null) { String getMsg="對方:"+msg+" "+ChatServer.getCurrentTime()+"\n"; ChatServer.displayInfo=ChatServer.displayInfo+getMsg; jtaChatRecord.setText(ChatServer.displayInfo); } } catch (SocketException e) { JOptionPane.showMessageDialog(null,"鏈接斷開!"); ChatServer.jlbIsStart.setForeground(Color.RED); ChatServer.jlbIsStart.setText("[鏈接斷開]"); ChatServer.jbtSend.setEnabled(false); }catch (IOException e) { e.printStackTrace(); } } }//用於發送信息的線程 class sendMsgToClient implements Runnable{ //DataOutputStream out; String sendMsg;
public sendMsgToClient(String sendMsg){ //this.out=out; this.sendMsg=sendMsg; } @Override public void run() { //System.out.println("S"+sendMsg); ChatServer.pw.println(sendMsg); ChatServer.pw.flush(); } }//監聽線程,避免阻死UI線程,因此這裏單獨做爲一個線程 class StartServer implements Runnable{ JLabel jlbIsStart; int port; DataInputStream inputFromClient; DataOutputStream outToClient; JTextArea jtaChatRecord;
StartServer(JLabel jlbIsStart,int port,DataInputStream inputFromClient, DataOutputStream outToClient,JTextArea jtaChatRecord){ this.jlbIsStart=jlbIsStart; this.port=port; this.inputFromClient=inputFromClient; this.outToClient=outToClient; this.jtaChatRecord=jtaChatRecord; }
@Override public void run() { try {
jlbIsStart.setForeground(Color.BLUE); jlbIsStart.setText("[正在啓動]"); @SuppressWarnings("resource") ServerSocket ssocket=new ServerSocket(port); jlbIsStart.setForeground(Color.BLACK); jlbIsStart.setText("[等待鏈接]");
while(true){ Socket socket=ssocket.accept(); jlbIsStart.setForeground(Color.GREEN); jlbIsStart.setText("[鏈接成功]"); ChatServer.jbtSend.setEnabled(true);
//得到數據輸入流 inputFromClient=new DataInputStream(socket.getInputStream());
//得到數據輸出流 outToClient=new DataOutputStream(socket.getOutputStream()); ChatServer.pw=new PrintWriter(outToClient);
Runnable getRun=new GetMsgFromClient(inputFromClient,jtaChatRecord); Thread getThread=new Thread(getRun); getThread.start();
}
}catch (BindException e) { JOptionPane.showMessageDialog(null,"端口被佔用!請換個端口試試"); jlbIsStart.setText("[端口占用]"); }catch (IOException e) { e.printStackTrace(); } } }
public class ChatClient extends JFrame{ private static final long serialVersionUID = 1L;
private static String ipSite="127.0.0.1"; private static int port=8000;
static String displayInfo="Visy:本程序的聊天記錄是保存在內存變量中的,因此注意:"+ "\n一、退出後內容會丟失,重要信息請複製到其餘地方保存\n二、"+ "聊天記錄過多時請及時點擊「清除記錄」清除,以避免內存不足\n----------------------------"+ "------------------------------------------------------\n\n";
private static JTextArea jtaContent=new JTextArea(""); static JButton jbtSend=new JButton("發送"); private static JTextArea jtaFromServer=new JTextArea(""); private JLabel jlbIp=new JLabel("對方IP:"); private JLabel jlbPort=new JLabel("端口:"); public static JLabel jlbIsCon; private JTextField jtfIp=new JTextField(8); private JTextField jtfPort=new JTextField(5); public static JButton jbtCon; private JButton jbtClear;
static DataOutputStream outputToServer; static DataInputStream inputFromServer; ChatClient() { //界面佈局---------------------------------------- JPanel panelTop=new JPanel(new FlowLayout()); panelTop.add(jlbIp); jtfIp.setText(ipSite);panelTop.add(jtfIp); panelTop.add(jlbPort); jtfPort.setText(""+port);panelTop.add(jtfPort); jbtCon=new JButton("鏈接");jbtCon.setBackground(Color.green);panelTop.add(jbtCon); jlbIsCon=new JLabel(" [還沒有鏈接]");jlbIsCon.setForeground(Color.RED);panelTop.add(jlbIsCon); jbtClear=new JButton(" 清除記錄");jbtClear.setBackground(Color.YELLOW);panelTop.add(jbtClear); panelTop.setBorder(new LineBorder(Color.BLACK));
JPanel panel1=new JPanel(new BorderLayout()); panel1.add(jtaContent,BorderLayout.CENTER); jbtSend.setEnabled(false); jbtSend.setBackground(Color.YELLOW);jbtSend.setMnemonic(KeyEvent.VK_ENTER);panel1.add(jbtSend,BorderLayout.EAST); panel1.setBorder(new LineBorder(Color.BLACK));
JPanel panel2=new JPanel(new BorderLayout()); //把定義的JTextArea放到JScrollPane裏面去 JScrollPane scrollPanel = new JScrollPane(jtaFromServer); //分別設置水平和垂直滾動條自動出現 scrollPanel.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollPanel.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
panel2.add(scrollPanel,BorderLayout.CENTER); panel2.setBorder(new TitledBorder("聊天記錄"));
JPanel panelDown=new JPanel(new BorderLayout()); panelDown.add(panel1,BorderLayout.SOUTH); panelDown.add(panel2,BorderLayout.CENTER);
add(panelTop,BorderLayout.NORTH); add(panelDown,BorderLayout.CENTER);
setTitle("客戶端"); setSize(500,390); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); //-------------------------------------------- //啓動和服務端的鏈接 jbtCon.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ipSite=jtfIp.getText(); port=Integer.parseInt(jtfPort.getText()); connectServer(); } }); //發送消息 jbtSend.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String sendInfo=jtaContent.getText(); String sendMsg="我:"+sendInfo+" "+getCurrentTime()+"\n"; displayInfo=displayInfo+sendMsg; jtaFromServer.setText(displayInfo); openSendThread(sendInfo); jtaContent.setText(""); } }); //清屏和聊天數據 jbtClear.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { displayInfo=""; jtaFromServer.setText(""); } }); } //獲取系統當前時間 public static String getCurrentTime(){ Calendar ca = Calendar.getInstance(); int y= ca.get(Calendar.YEAR);//獲取年份 int m=ca.get(Calendar.MONTH)+1;//獲取月份 int d=ca.get(Calendar.DATE);//獲取日 int h=ca.get(Calendar.HOUR_OF_DAY);//小時 int min=ca.get(Calendar.MINUTE);//分 int s=ca.get(Calendar.SECOND);//秒 return "["+y+"/"+m+"/"+d+" "+h+":"+min+":"+s+"]"; }
//經過IP地址和端口號得到一個socket @SuppressWarnings("resource") Socket socket=new Socket(ipSite,port); jlbIsCon.setForeground(Color.GREEN); jlbIsCon.setText(" [鏈接成功]"); jbtSend.setEnabled(true); jbtCon.setText("刷新"); //System.out.println("客戶端已啓動###");
//得到數據輸入流 inputFromServer=new DataInputStream(socket.getInputStream());
//得到數據輸出流 outputToServer=new DataOutputStream(socket.getOutputStream());
Runnable getRun=new GetMsgFromServer(inputFromServer,jtaFromServer); Thread getThread=new Thread(getRun); getThread.start();
}catch (Exception e) { JOptionPane.showMessageDialog(null, "鏈接服務器失敗!"); jbtSend.setEnabled(false); jlbIsCon.setForeground(Color.RED); jlbIsCon.setText(" [鏈接失敗]"); jbtCon.setText("鏈接"); } }
public void openSendThread(String sendMsg){ Runnable sendRun=new SendMsgToServer(outputToServer,sendMsg); Thread sendThread=new Thread(sendRun); sendThread.start(); }
public GetMsgFromServer(DataInputStream in,JTextArea jtaFromServer){ this.in=in; this.jtaInput=jtaFromServer; }
@Override public void run() { try { BufferedReader br=new BufferedReader(new InputStreamReader(in)); String msg=""; while ((msg = br.readLine()) != null) { String getMsg="對方:"+msg+" "+ChatClient.getCurrentTime()+"\n"; ChatClient.displayInfo=ChatClient.displayInfo+getMsg; jtaInput.setText(ChatClient.displayInfo); } } catch (IOException e) { JOptionPane.showMessageDialog(null,"鏈接斷開!"); ChatClient.jbtSend.setEnabled(false); ChatClient.jlbIsCon.setForeground(Color.RED); ChatClient.jlbIsCon.setText(" [鏈接掉線]"); ChatClient.jbtCon.setText("鏈接"); } } }//發送信息到服務端的線程 class SendMsgToServer implements Runnable{ private DataOutputStream out; private String sendMsg; public SendMsgToServer(DataOutputStream out,String sendMsg){ this.out=out; this.sendMsg=sendMsg; }
public void run() { PrintWriter pw=new PrintWriter(out, true); pw.println(sendMsg); } }