Tcp与Udp
来源:互联网 发布:unctad数据库怎么用 编辑:程序博客网 时间:2024/06/05 14:46
数据在网路上传输,一般要遵守一些协议.而现实中最常见的网络传输协议莫过于tcp/ip协议.该协议将网络分成不同的层次,一般而言
,可分成:物理数据链路层,网路层,传输层,应用层.而今要讨论的Tcp/udp协议是属于传输层的协议.而与该协议密切相关的概念要数ip地址与计算机端口的概念.网路世界通过ip与端口,来实现逻辑上每台计算机的寻址,从而可以通讯,记住,这样的地址也只是逻辑上的寻址.置于如何寻址,请参考其他资料.
计算机通过寻址,找到了目标之后,就渴望通讯.而在通讯的过程中,就该传输层而言,要数TCp与udp最为常见.那么他们是怎样的通讯方式呢?
对于udp而言,其是面向无连接的协议,也就是说,双方通讯不需要两方同时建立联系.所以是一种不可靠的传输协议,但同时也是一种相对而言,传输速度比较快的协议.常常应用于局域网中,例如同步语音,同步视频等等.
而对于tcp而言,其是面向连接的协议,也就是说,双方通讯需要两方同时建立联系.所以是一种可靠的传输协议,但同时也是一种相对而言,传输速度比较慢的协议.
先介绍udp编程:
在java中,udp的编程主要用到了两个类:
DatagramSocket 通过ip地址与端口来创建套接字
DatagramPacket 在传输的过程中传递的数据包.可用来发送数据,
也可以用来接收数据.(通常开启一个独立的线程执行代码)
一段典型的代码片段:
发送端:
class Sender implements Runnable{ private DatagramSocket socket; private Scanner scanner; public Sender(){ try { socket=new DatagramSocket(1000); scanner=new Scanner(System.in); } catch (SocketException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void run() { // TODO Auto-generated method stub try { while(true){ System.out.println("开始输入:"); String line=scanner.nextLine(); DatagramPacket packet=new DatagramPacket(line.getBytes(),line.getBytes().length, InetAddress.getLocalHost(), 20000); socket.send(packet); if("bye".equals(line)){ break; } Thread.sleep(500); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(socket!=null){ socket.close(); } } }
接收端的代码:
class Reciver implements Runnable{ private DatagramSocket socket; public Reciver(){ try { socket=new DatagramSocket(20000); } catch (SocketException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void run() { // TODO Auto-generated method stub try { while(true){ byte[] buffer=new byte[1024]; DatagramPacket packet=new DatagramPacket(buffer, buffer.length); socket.receive(packet); String str=new String(buffer,0,packet.getLength()); System.out.println("接收到的数据:"+str); if("bye".equals(str)){ break; } Thread.sleep(500); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(socket!=null){ socket.close(); } } }
对于发送与接收方而言,在系统中申请端口,就可以发送与接收信息.
在发送的数据包中,不仅存放数据,而且需要指定数据传送的目标地址,即可.
接下来介绍Tcp简单编程.经典的tcp示例是简单的群聊系统.
思路:
对于我们客户而言,开启两个线程来不断的读写操作.
对于服务端,其中有链接的管理类,来负责链接的接收与移除.
当有链接建立时,开启新的线程来负责聊天转发.
注意:在这里,我将套接字的管理类设计成单例模式,而且在添加或者删除连接时,注意多线程的访问问题,设计成线程安全的.
在这里用代码实现:
客户端:
向服务器写入数据的线程:
/* * 向目标写数据 */class Writer implements Runnable{ private OutputStream os; private PrintWriter pw; private Scanner scanner; public Writer(OutputStream os){ this.os=os; pw=new PrintWriter(os); scanner=new Scanner(System.in); } @Override public void run() { // TODO Auto-generated method stub while(true){ System.out.println("开始写数据:"); String line=scanner.nextLine(); pw.println(line); pw.flush(); if("bye".equals(line)){ pw.close(); break; } } }}
向服务器读取数据的线程:
//从服务端读取数据class Reader implements Runnable{ private InputStream is; private BufferedReader br; public Reader(InputStream is){ this.is=is; br=new BufferedReader(new InputStreamReader(is)); } @Override public void run() { // TODO Auto-generated method stub while(true){ try { String line=br.readLine(); System.out.println(line); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }}
然后开启线程,进行读取与写入:
public class Client { public static void main(String[] args) { System.out.println("请输入要开启的端口号:(1024-65535)"); Scanner scanner=new Scanner(System.in); String portStr=scanner.nextLine(); int port=Integer.parseInt(portStr); Socket socket=null; try { socket=new Socket(InetAddress.getLocalHost(),20000,InetAddress.getLocalHost(),port); /* * 开启读写进程 */ new Thread(new Writer(socket.getOutputStream())).start(); new Thread(new Reader(socket.getInputStream())).start(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
套接字的管理类:
/* * 设计成单例模式 */ /* */public class SocketManager { private static List<Socket> list=new ArrayList<Socket>(); private static SocketManager manager; private SocketManager(){ } public static SocketManager getInstance(){ if(manager==null){ manager=new SocketManager(); } return manager; } //添加连接 public void addSocket(Socket socket){ synchronized(list){ list.add(socket); } } //移除连接 public void removeSocket(Socket socket){ synchronized(list){ list.remove(socket); } } //返回所有的socket public List<Socket> getAllSockets(){ return list; }}
对于服务端:
等待接入的连接,开启转发线程:
public class Server { private SocketManager manager; private ServerSocket server; public SocketManager getManager() { return manager; } public ServerSocket getServer() { return server; } public Server(){ manager=SocketManager.getInstance(); try { server=new ServerSocket(20000); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { Server server=new Server(); ServerSocket Serversocket = null; //不断的等待接入连接 try { while(true){ Serversocket=server.getServer(); Socket socket=Serversocket.accept(); //添加到管理器中 server.getManager().addSocket(socket); new Thread(new Chart(socket)).start(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(Serversocket!=null){ try { Serversocket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }}
转发线程:
/* * 获取输入的内容,并将转发到其他的连接上 */class Chart implements Runnable{ private Socket socket; private BufferedReader br=null; private PrintWriter pw=null; private SocketManager manager; public Chart(Socket socket){ this.socket=socket; try { br=new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } manager=SocketManager.getInstance(); } @Override public void run() { // TODO Auto-generated method stub try { while(true){ String line=null; while((line=br.readLine())!=null){ System.out.println(socket.getInetAddress()+"说:"+line); for(int i=0;i<manager.getAllSockets().size();i++){ Socket socket=manager.getAllSockets().get(i); if(socket!=this.socket){ pw=new PrintWriter(socket.getOutputStream()); pw.println(socket.getInetAddress()+"说:"+line); pw.flush(); } } } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ manager.removeSocket(this.socket); } }}
- TCP与UDP
- 摘录:TCP与UDP
- UDP与TCP比较
- TCP与UDP比较
- TCP与UDP区别
- TCP与UDP区别
- UDP/TCP与fork
- TCP与UDP
- TCP与UDP区别
- UDP与TCP协议
- TCP与UDP
- TCP与UDP区别
- TCP 与 UDP对比
- Socket与TCP、UDP
- TCP与UDP区别
- TCP与UDP区别
- TCP与UDP区别
- HTTP与TCP/UDP
- 【CODEFORCES】 C. Number of Ways
- Balloon Comes!
- Fibonacci Again
- ubuntu下ibus无法启动
- Number Sequence
- Tcp与Udp
- java直接用jdbc操作oracle数据库
- memcached
- 不容易系列之一
- DSAPI多功能组件编程应用-文件类
- 过年回家晕车怎么办?给正在车上的小伙伴!
- 【网络流】 SGU 194 Reactor Cooling
- Uva 455-periodic strings
- Cordova3.X 环境搭建