电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

java實現基于UDP協議網絡Socket編程(C/S通信)

瀏覽:3日期:2022-08-21 17:46:32

一、前言:認識UDP

UDP,全稱User Datagram Protocol(用戶數據報協議),是Internet 協議集支持一個無連接的傳輸協議。UDP 為應用程序提供了一種無需建立連接就可以發送封裝的 IP 數據包的方法。

UDP主要用于不要求分組順序到達的傳輸中,分組傳輸順序的檢查與排序由應用層完成,提供面向報文的簡單不可靠信息傳送服務。UDP 協議基本上是IP協議與上層協議的接口,適用端口分別運行在同一臺設備上的多個應用程序。

二、UDP的特點(與TCP相比)

正是UDP提供不可靠服務,具有了TCP所沒有的優勢。無連接使得它具有資源消耗小,處理速度快的優點,所以音頻、視頻和普通數據在傳送時經常使用UDP,偶爾丟失一兩個數據包,也不會對接收結果產生太大影響。

UDP有別于TCP,有自己獨立的套接字(IP+Port),它們的端口號不沖突。和TCP編程相比,UDP在使用前不需要進行連接,沒有流的概念。

如果說TCP協議通信與電話通信類似,那么UDP通信就與郵件通信類似:不需要實時連接,只需要目的地址;

UDP通信前不需要建立連接,只要知道地址(ip地址和端口號)就可以給對方發送信息;

基于用戶數據報文(包)讀寫;

UDP通信一般用于線路質量好的環境,如局域網內,如果是互聯網,往往應用于對數據完整性不是過于苛刻的場合,例如語音傳送等。

以上是對UDP的基本認識,與以前學習的理論相比,接下來的實踐更加有趣,實踐出真知。

三、UDP網絡Socket編程(Java實現)

首先,熟悉java中UDP編程的幾個關鍵類:DatagramSocket(套接字類),DatagramPacket(數據報類),MulticastSocket。本篇主要使用前兩個。

1、創建客戶端

第一步,實例化一個數據報套接字,用于與服務器端進行通信。與TCP不同,UDP中只有DatagramSocket一種套接字,不區分服務端和客戶端,創建的時候并不需要指定目的地址,這也是TCP協議和UDP協議最大的不同點之一。

public UDPClient(String remoteIP,String remotePort) throws IOException{ this.remoteIP=InetAddress.getByName(remoteIP); this.remotePort=Integer.parseInt(remotePort); //創建UDP套接字,系統隨機選定一個未使用的UDP端口綁定 socket=new DatagramSocket();}

第二步, 創建UDP數據報,實現發送和接收數據的方法。UDP發送數據是基于報文DatagramPacket,網絡中傳遞的UDP數據都要封裝在這種自包含的報文中。

實現DatagramPacket發送數據的方法:

//定義一個數據的發送方法public void send(String msg){ try { //將待發送的字符串轉為字節數組 byte[] outData=msg.getBytes('utf-8'); //構建用于發送的數據報文,構造方法中傳入遠程通信方(服務器)的ip地址和端口 DatagramPacket outPacket=new DatagramPacket(outData,outData.length,remoteIP,remotePort); //給UDP發送數據報 socket.send(outPacket); }catch (IOException e){ e.printStackTrace(); }}

DatagramPacket接收數據的方法:

//定義一個數據的發送方法public void send(String msg){ try { //將待發送的字符串轉為字節數組 byte[] outData=msg.getBytes('utf-8'); //構建用于發送的數據報文,構造方法中傳入遠程通信方(服務器)的ip地址和端口 DatagramPacket outPacket=new DatagramPacket(outData,outData.length,remoteIP,remotePort); //給UDP發送數據報 socket.send(outPacket); }catch (IOException e){ e.printStackTrace(); }}

可以看到,發送和接收數據中使用DatagramSocket的實例的send和receive方法,這就是數據報套接字的兩個重要方法。

通信結束,銷毀Socket的方法如下:

public void close(){ if (socket!=null) socket.close();}

到這里,客戶端已全部完成,等待接下來與服務端的通信...

2、客戶端圖形界面

現在,設計客戶端通信的簡單界面,一方面可以更方便的和服務器連續對話通信,另一方面,有了圖形界面,體驗感更加!圖形化界面主要使用JavaFX實現,代碼容易看懂。

import javafx.application.Application;import javafx.event.EventHandler;import javafx.geometry.Insets;import javafx.geometry.Pos;import javafx.scene.Scene;import javafx.scene.control.*;import javafx.scene.input.KeyCode;import javafx.scene.input.KeyEvent;import javafx.scene.layout.BorderPane;import javafx.scene.layout.HBox;import javafx.scene.layout.Priority;import javafx.scene.layout.VBox;import javafx.stage.Stage;import java.io.IOException;public class UDPClientFX extends Application { private Button btnExit=new Button('退出'); private Button btnSend = new Button('發送'); private TextField tfSend=new TextField();//輸入信息區域 private TextArea taDisplay=new TextArea();//顯示區域 private TextField ipAddress=new TextField();//填寫ip地址 private TextField tfport=new TextField();//填寫端口 private Button btConn=new Button('連接'); private UDPClient UDPClient; private String ip; private String port; @Override public void start(Stage primaryStage) { BorderPane mainPane=new BorderPane(); //連接服務器區域 HBox hBox1=new HBox(); hBox1.setSpacing(10); hBox1.setPadding(new Insets(10,20,10,20)); hBox1.setAlignment(Pos.CENTER); hBox1.getChildren().addAll(new Label('ip地址:'),ipAddress,new Label('端口:'),tfport,btConn); mainPane.setTop(hBox1); VBox vBox=new VBox(); vBox.setSpacing(10); vBox.setPadding(new Insets(10,20,10,20)); vBox.getChildren().addAll(new Label('信息顯示區'),taDisplay,new Label('信息輸入區'),tfSend); VBox.setVgrow(taDisplay, Priority.ALWAYS); mainPane.setCenter(vBox); HBox hBox=new HBox(); hBox.setSpacing(10); hBox.setPadding(new Insets(10,20,10,20)); hBox.setAlignment(Pos.CENTER_RIGHT); hBox.getChildren().addAll(btnSend,btnExit); mainPane.setBottom(hBox); Scene scene =new Scene(mainPane,700,500); primaryStage.setScene(scene); primaryStage.show(); //連接服務器之前,發送bye后禁用發送按鈕,禁用Enter發送信息輸入區域,禁用下載按鈕 btnSend.setDisable(true); tfSend.setDisable(true); //連接按鈕 btConn.setOnAction(event -> { ip=ipAddress.getText().trim(); port=tfport.getText().trim(); try {UDPClient = new UDPClient(ip,port);//連接服務器之后未結束服務前禁用再次連接btConn.setDisable(true);//重新連接服務器時啟用輸入發送功能tfSend.setDisable(false);btnSend.setDisable(false); } catch (IOException e) {e.printStackTrace(); } }); //發送按鈕事件 btnSend.setOnAction(event -> { String msg=tfSend.getText(); UDPClient.send(msg);//向服務器發送一串字符 taDisplay.appendText('客戶端發送:'+msg+'n'); String Rmsg=null; Rmsg=UDPClient.receive();// System.out.println(Rmsg); taDisplay.appendText(Rmsg+'n'); if (msg.equals('bye')){btnSend.setDisable(true);//發送bye后禁用發送按鈕tfSend.setDisable(true);//禁用Enter發送信息輸入區域//結束服務后再次啟用連接按鈕btConn.setDisable(false); } tfSend.clear(); }); //對輸入區域綁定鍵盤事件 tfSend.setOnKeyPressed(new EventHandler<KeyEvent>() { @Override public void handle(KeyEvent event) {if(event.getCode()==KeyCode.ENTER){ String msg=tfSend.getText(); UDPClient.send(msg);//向服務器發送一串字符 taDisplay.appendText('客戶端發送:'+msg+'n'); String Rmsg=null; Rmsg=UDPClient.receive(); taDisplay.appendText(Rmsg+'n'); if (msg.equals('bye')){ tfSend.setDisable(true);//禁用Enter發送信息輸入區域 btnSend.setDisable(true);//發送bye后禁用發送按鈕 //結束服務后再次啟用連接按鈕 btConn.setDisable(false); } tfSend.clear();} } });btnExit.setOnAction(event -> { try {exit(); } catch (InterruptedException e) {e.printStackTrace(); } }); //窗體關閉響應的事件,點擊右上角的×關閉,客戶端也關閉 primaryStage.setOnCloseRequest(event -> { try {exit(); } catch (InterruptedException e) {e.printStackTrace(); } }); //信息顯示區鼠標拖動高亮文字直接復制到信息輸入框,方便選擇文件名 //taDispaly為信息選擇區的TextArea,tfSend為信息輸入區的TextField //為taDisplay的選擇范圍屬性添加監聽器,當該屬性值變化(選擇文字時),會觸發監聽器中的代碼 taDisplay.selectionProperty().addListener(((observable, oldValue, newValue) -> { //只有當鼠標拖動選中了文字才復制內容 if(!taDisplay.getSelectedText().equals(''))tfSend.setText(taDisplay.getSelectedText()); })); } private void exit() throws InterruptedException { if (UDPClient!=null){ //向服務器發送關閉連接的約定信息 UDPClient.send('bye'); UDPClient.close(); } System.exit(0); } public static void main (String[] args) { launch(args); }}

重點在各個控件的事件處理邏輯上,需避免要一些誤操作導致異常拋出,如:連接服務器前禁用發送按鈕,在連接服務器成功后禁用連接按鈕,禁用輸入區等。另外,實現了回車發送的快捷功能,詳見代碼的鍵盤事件綁定部分。

還有,約定發送'bye'或者退出按鈕結束通信關閉Socket。

java實現基于UDP協議網絡Socket編程(C/S通信)

成功連接后:

java實現基于UDP協議網絡Socket編程(C/S通信)

3、創建服務器端

服務器端為客戶端提供服務,實現通信。這里包括了幾個方法Service(),udpSend()和udpReceive().

首先,我將UDP數據報發送和接收寫成一個方法,作為整體方便多次調用。

public DatagramPacket udpReceive() throws IOException { DatagramPacket receive; byte[] dataR = new byte[1024]; receive = new DatagramPacket(dataR, dataR.length); socket.receive(receive); return receive;}public void udpSend(String msg,InetAddress ipRemote,int portRemote) throws IOException { DatagramPacket sendPacket; byte[] dataSend = msg.getBytes(); sendPacket = new DatagramPacket(dataSend,dataSend.length,ipRemote,portRemote); socket.send(sendPacket);}

與TCP的Socket通信不同,需要將數據轉化成字節數據形式,封裝成數據報進行傳輸,接收時解析數據為字節,再進行讀取。

服務器端核心部分為Service()方法,實例化一個DatagramSocket類套接字,實現循環與客戶端的通信。

與客戶端約定的結束標志'bye'進行處理,結束對話。

public DatagramPacket udpReceive() throws IOException { DatagramPacket receive; byte[] dataR = new byte[1024]; receive = new DatagramPacket(dataR, dataR.length); socket.receive(receive); return receive;}public void udpSend(String msg,InetAddress ipRemote,int portRemote) throws IOException { DatagramPacket sendPacket; byte[] dataSend = msg.getBytes(); sendPacket = new DatagramPacket(dataSend,dataSend.length,ipRemote,portRemote); socket.send(sendPacket);}

四、服務器端和客戶端完整代碼

服務器端:

public DatagramPacket udpReceive() throws IOException { DatagramPacket receive; byte[] dataR = new byte[1024]; receive = new DatagramPacket(dataR, dataR.length); socket.receive(receive); return receive;}public void udpSend(String msg,InetAddress ipRemote,int portRemote) throws IOException { DatagramPacket sendPacket; byte[] dataSend = msg.getBytes(); sendPacket = new DatagramPacket(dataSend,dataSend.length,ipRemote,portRemote); socket.send(sendPacket);}

客戶端:

//UDPClient.javaimport java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;public class UDPClient { private int remotePort; private InetAddress remoteIP; private DatagramSocket socket; //用于接收數據的報文字節數組緩存最最大容量,字節為單位 private static final int MAX_PACKET_SIZE=512; public UDPClient(String remoteIP,String remotePort) throws IOException{ this.remoteIP=InetAddress.getByName(remoteIP); this.remotePort=Integer.parseInt(remotePort); //創建UDP套接字,系統隨機選定一個未使用的UDP端口綁定 socket=new DatagramSocket(); } //定義一個數據的發送方法 public void send(String msg){ try { //將待發送的字符串轉為字節數組 byte[] outData=msg.getBytes('utf-8'); //構建用于發送的數據報文,構造方法中傳入遠程通信方(服務器)的ip地址和端口 DatagramPacket outPacket=new DatagramPacket(outData,outData.length,remoteIP,remotePort); //給UDP發送數據報 socket.send(outPacket); }catch (IOException e){ e.printStackTrace(); } } public String receive(){ String msg; //準備空的數據報文 DatagramPacket inPacket=new DatagramPacket(new byte[MAX_PACKET_SIZE],MAX_PACKET_SIZE); try { //讀取報文,阻塞語句,有數據就裝包在inPacket報文中,以裝完或裝滿為止 socket.receive(inPacket); //將接收到的字節數組轉為對應的字符串 msg=new String(inPacket.getData(),0,inPacket.getLength(),'utf-8'); } catch (IOException e) { e.printStackTrace(); msg=null; } return msg; } public void close(){ if (socket!=null) socket.close(); }}

五、效果展示

java實現基于UDP協議網絡Socket編程(C/S通信)

六、總結

這一篇詳細記錄學習運用java進行網絡編程,基于UDP套接字(Socket)實現服務器與客戶端間的通信,在實戰案例中更深刻理解UDP的實現原理,掌握UDP實踐應用步驟。

起初完成UDP通信時,遇到了幾個問題,相比較TCP的實現,確實體會到數據傳輸的過程的不同,UDP服務和客戶端共用了一個DatagramSocket,另外需要DatagramPacket數據報的協作。另外,UDP沒有數據流的概念,所以讀寫不同于TCP,需要以字節數據進行讀取。

到此這篇關于java實現基于UDP協議網絡Socket編程(C/S通信)的文章就介紹到這了,更多相關java UDP協議Socket編程內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
主站蜘蛛池模板: 早报网 | 混合气体腐蚀试验箱_盐雾/硫化氢/气体腐蚀试验箱厂家-北京中科博达 | [品牌官网]贵州遵义双宁口腔连锁_贵州遵义牙科医院哪家好_种植牙_牙齿矫正_原华美口腔 | 开云(中国)Kaiyun·官方网站 - 登录入口| 小程序开发公司-小程序制作-微信小程序开发-小程序定制-咏熠软件 | 成都网站建设制作_高端网站设计公司「做网站送优化推广」 | 精密钢管,冷拔精密无缝钢管,精密钢管厂,精密钢管制造厂家,精密钢管生产厂家,山东精密钢管厂家 | 电缆故障测试仪_电缆故障定位仪_探测仪_检测仪器_陕西意联电气厂家 | 仿真茅草_人造茅草瓦价格_仿真茅草厂家_仿真茅草供应-深圳市科佰工贸有限公司 | 深圳美安可自动化设备有限公司,喷码机,定制喷码机,二维码喷码机,深圳喷码机,纸箱喷码机,东莞喷码机 UV喷码机,日期喷码机,鸡蛋喷码机,管芯喷码机,管内壁喷码机,喷码机厂家 | 淬火设备-钎焊机-熔炼炉-中频炉-锻造炉-感应加热电源-退火机-热处理设备-优造节能 | 云阳人才网_云阳招聘网_云阳人才市场_云阳人事人才网_云阳人家招聘网_云阳最新招聘信息 | 分轨 | 上传文件,即刻分离人声和伴奏 | 户外环保不锈钢垃圾桶_标识标牌制作_园林公园椅厂家_花箱定制-北京汇众环艺 | (中山|佛山|江门)环氧地坪漆,停车场地板漆,车库地板漆,聚氨酯地板漆-中山永旺地坪漆厂家 | 镀锌钢格栅_热镀锌格栅板_钢格栅板_热镀锌钢格板-安平县昊泽丝网制品有限公司 | 电加热导热油炉-空气加热器-导热油加热器-翅片电加热管-科安达机械 | 电动液压篮球架_圆管地埋式篮球架_移动平箱篮球架-强森体育 | 安徽控制器-合肥船用空调控制器-合肥家电控制器-合肥迅驰电子厂 安徽净化板_合肥岩棉板厂家_玻镁板厂家_安徽科艺美洁净科技有限公司 | 翰墨AI智能写作助手官网_人工智能问答在线AI写作免费一键生成 | 楼梯定制_楼梯设计施工厂家_楼梯扶手安装制作-北京凌步楼梯 | 在线PH计-氧化锆分析仪-在线浊度仪-在线溶氧仪- 无锡朝达 | 聚丙烯酰胺_厂家_价格-河南唐达净水材料有限公司 | 不锈钢水管-不锈钢燃气管-卫生级不锈钢管件-不锈钢食品级水管-广东双兴新材料集团有限公司 | 石家庄小程序开发_小程序开发公司_APP开发_网站制作-石家庄乘航网络科技有限公司 | 行吊_电动单梁起重机_双梁起重机_合肥起重机_厂家_合肥市神雕起重机械有限公司 | 塑料造粒机「厂家直销」-莱州鑫瑞迪机械有限公司 | 篮球地板厂家_舞台木地板品牌_体育运动地板厂家_凯洁地板 | 冷却塔减速机器_冷却塔皮带箱维修厂家_凉水塔风机电机更换-广东康明冷却塔厂家 | 莱州网络公司|莱州网站建设|莱州网站优化|莱州阿里巴巴-莱州唯佳网络科技有限公司 | 热处理温控箱,热处理控制箱厂家-吴江市兴达电热设备厂 | LED太阳能中国结|发光红灯笼|灯杆造型灯|节日灯|太阳能灯笼|LED路灯杆装饰造型灯-北京中海轩光电 | 陕西安闸机-伸缩门-车牌识别-广告道闸——捷申达门业科技 | 浙江华锤电器有限公司_地磅称重设备_防作弊地磅_浙江地磅售后维修_无人值守扫码过磅系统_浙江源头地磅厂家_浙江工厂直营地磅 | MES系统-WMS系统-MES定制开发-制造执行MES解决方案-罗浮云计算 | 意大利Frascold/富士豪压缩机_富士豪半封闭压缩机_富士豪活塞压缩机_富士豪螺杆压缩机 | 密封无忧网 _ 专业的密封产品行业信息网 | 挤奶设备过滤纸,牛奶过滤纸,挤奶机过滤袋-济南蓝贝尔工贸有限公司 | TPE塑胶原料-PPA|杜邦pom工程塑料、PPSU|PCTG材料、PC/PBT价格-悦诚塑胶 | 活性氧化铝|无烟煤滤料|活性氧化铝厂家|锰砂滤料厂家-河南新泰净水材料有限公司 | Trimos测长机_测高仪_TESA_mahr,WYLER水平仪,PWB对刀仪-德瑞华测量技术(苏州)有限公司 |