网络编程-TCP和UDP


客户机通过IP加端口号来访问连接服务器上提供的网络服务
端口号可以唯一标识一个服务,不同类型的服务可以共用同一个端口号

Socket套接字,服务器可以用ServerSocket监听客户机的连接,需要用IP和PORT来构建一个ServerSocket
当调用ServerSocket.accept()方法时,服务器一直阻塞在此,等待客户机的连接,返回的Socket包含了客户机的一些信息

可以通过返回的Socket来和客户机交流,Socket.getOutputStream()来往客户机写数据,Socket.getInputStream()来读取客户机的写给服务机的数据

客户机(使用Socket)要想跟服务机取得连接,必须要指定服务机的IP和提供该服务的场所(端口号),使用Socket.getOutputStream()和Socket.getInputStream()来读写数据

客户机和服务机写数据时,必须刷新缓冲区(数据是被写到缓冲区内的),否则只有当默认的缓冲区满时,数据才会进行传输

由于Socket使用了非常重要的非内存资源,所以必须谨慎正确的清除它

下面是一个简单的客户机和服务器连接通信的例子
public class TCPServer {

	public static final int PORT = 8090;
	
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {

		ServerSocket s = new ServerSocket(PORT);
		
		System.out.println("s:"+s);
		
		try{
			Socket scoket = s.accept();
			System.out.println("scoket:"+scoket);
			try{
				
				BufferedReader in = new BufferedReader(
						new InputStreamReader(
								scoket.getInputStream()));
				
				//自动刷新缓冲区,否则要当缓冲区慢才会进行传输
				PrintWriter out = new PrintWriter(
						new BufferedWriter(
								new OutputStreamWriter(
										scoket.getOutputStream())),true);
				
				while(true){
					
					//和client实现一次“握手”
					
					String str = in.readLine();
					//连接结束的条件
					if(str.equals("END")) break;
					System.out.println("Echoing:"+str);
					//send package to client
					out.println(str);
					
				}
				
				
			}finally{
				scoket.close();
			}
		}finally{
			s.close();
		}
		
		
	}

}

public class TCPClient {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {

		InetAddress inetAddress = InetAddress.getByName(null);
		System.out.println("inetAddress:"+inetAddress);
		
		Socket socket = new Socket(inetAddress,TCPServer.PORT);
		System.out.println("socket:"+socket);
		
		try{
			
			BufferedReader in = new BufferedReader(
					new InputStreamReader(
							socket.getInputStream()));
			
			//自动刷新缓冲区,否则要当缓冲区慢才会进行传输
			PrintWriter out = new PrintWriter(
					new BufferedWriter(
							new OutputStreamWriter(
									socket.getOutputStream())),true);
			for(int i=0;i<10;i++){
				//send package to server ,wait server echo
				out.println("Hello "+i);
				String str = in.readLine();
				System.out.println("Enchoing:"+str);
			}
			out.println("END");
		}finally{
			socket.close();
		}
	}

}

TCP是一种可靠的传输协议,它可以确保传输的数据准确的到达目的地而不会有数据的丢失,而UDP是一种不可靠的传输协议,有可能传输的数据中会给你丢失一部分,TCP需要占用非常大的资源且数据传输的比较慢,而UDP占用资源小且数据传输快

UDP是以一种数据包的形式陈列的,数据包在传输的过程中有可能丢失,也有可能传输的顺序会发生改变,但如果对传输速度要求比较快的话,UDP还是有用武之地的,向QQ、网络游戏啥的

下面是一个简单的UDP例子

public class UDPServer {

	public static int serverPort = 8097;
	DatagramSocket socket;
	//提供一个缓冲区,用于存放接收的数据
	byte[] buf = new byte[1000];
	//保存数据信息的场所
	DatagramPacket dp = new DatagramPacket(buf,buf.length);
	
	public UDPServer(){
		
		
		
		try {
			//要指定监听那个端口
			socket = new DatagramSocket(serverPort);
			System.out.println("socket:"+socket);
			
			while(true){
				
				//阻塞
				socket.receive(dp);
				
				//通过接收的数据包可以取得发包方的信息
				String receiveData = "receive data:"+Dgram.toString(dp)+" from inetAddress:"+dp.getAddress()+" the port:"+dp.getPort();
				System.out.println("receiveData:"+receiveData);
				
				String echoing = "echo "+receiveData;
				//发送到那个地址和端口
				socket.send(Dgram.toDatagram(echoing, dp.getAddress(), dp.getPort()));
				
				
			}
			
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		new UDPServer();
	}
}

public class UDPClient extends Thread{

	DatagramSocket socket;
	byte[] buf = new byte[1000];
	DatagramPacket dp = new DatagramPacket(buf,buf.length);
	int clientId;
	InetAddress serverAddress;
	
	public UDPClient(int id) {
		clientId = id;
		try {
			socket = new DatagramSocket();
			serverAddress = InetAddress.getByName("localhost");
			System.out.println("serverAddress:"+serverAddress);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (SocketException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void run() {
		
		for (int i = 0; i < 10; i++) {
			String sendMsg = "Client "+clientId+" Message "+i;
			try {
				
				//指定发送到地址和端口
				socket.send(Dgram.toDatagram(sendMsg, serverAddress, UDPServer.serverPort));
				
				socket.receive(dp);
				
				//数据包可以取得发包方的信息
				String receiveData = "Client "+clientId+" from address "+dp.getAddress()+" and port "+dp.getPort()
						+" receive data "+Dgram.toString(dp);
				System.out.println("receive data "+receiveData);
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
			
		}
		
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		
		for (int i = 0; i < 15; i++){
			new UDPClient(i).start();
		}
		
	}

}

用到的工具类

public class Dgram {

	public static DatagramPacket toDatagram(String str,
			InetAddress ia,int inetPort){
		
		byte[]  buf = new byte[str.length()];
		buf = str.getBytes();
		
		return new DatagramPacket(buf, buf.length,ia, inetPort);
	}
	
	public static String toString(DatagramPacket dp){
		return new String(dp.getData(),0,dp.getLength());
	} 
}


最后附上一个示例程序,其中包含了TCP服务多个客户机程序


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值