Java Socket编程 - 简单的问候服务实现

简介: 服务器端: 实现一个最简单的Hello服务,打印输出客户端IP地址到控制台,对任何连接的客户端都 会发送一串字符(Hello, Java Socket)然后关闭与客户端连接。等待下一个客户端的连接 请求到来。

服务器端:

实现一个最简单的Hello服务,打印输出客户端IP地址到控制台,对任何连接的客户端都

会发送一串字符(Hello, Java Socket)然后关闭与客户端连接。等待下一个客户端的连接

请求到来。

客户端:

实现一个最简单的Socket连接到Hello服务器端,接受服务器端发送过来的字节数据

打印并输出内容到控制台。

关键技巧:

由于JAVA中提供非常多的输入与输出流API,导致很多初学者接触JAVA SOCKET编程

时,由于对网络字节通信的本质缺乏了解,直接一个readline()去接受Socket字节流。

但是由于发送一方并没有发送/r/n导致一直无法读到数据,这个是最常见的一个错误。

另外一些常见的错误包括没有初始化接受缓冲区导致字符乱码,没有按照读入接受到

字节数重新组装,导致接受到的数据异常。所以代码演示了什么叫按字节发送与按字

节接受,这个是网络编程中非常重要的概念与原则。让那些输入流println()方法与输

出流readline()方法见鬼去吧,不是不好用,而是我建议你不要用,因为那些会妨碍你

的网络编程本质的认识与理解。另外我要特别说明一下:有时候flush()真的不是必须的

除非你使用了带有缓冲的输入与输出流来读写字节。

服务器端代码:

package com.gloomyfish.socket.tutorial.two;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class HelloService extends Thread {
	private ServerSocket serverSocket;
	public HelloService(int port) throws IOException {
		serverSocket = new ServerSocket(port);
	}

	public void run()
	{
		try {
			while(true)
			{
				System.out.println("Waiting for client on port " + serverSocket.getLocalPort());
				Socket client = serverSocket.accept(); // blocked & waiting for income socket
				System.out.println("Just connected to " + client.getRemoteSocketAddress());
				DataOutputStream dos = new DataOutputStream(client.getOutputStream());
				byte[] hello = "Hello, Java Socket".getBytes();
				dos.write(hello, 0, hello.length);
				dos.close();
				client.close();
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		try {
			HelloService service = new HelloService(9999);
			service.start();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
服务器在端口9999监听并等待连接,使用Java Thread来实现服务器端启动。

客户端代码如下:

package com.gloomyfish.socket.tutorial.two;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

public class HelloClient {
	private int clientNumber;
	private SocketAddress address;
	public HelloClient(int clientNum) {
		clientNumber = clientNum;
	}
	
	public void setupClients(String serverHostName, int port) throws IOException {
		address = new InetSocketAddress(serverHostName, port);
		for(int i=0; i<clientNumber; i++) {
			System.out.println();
			System.out.println("start client No. " + (i+1));
			Socket socket = new Socket();
			socket.connect(address);
			DataInputStream bufferedReader = new DataInputStream(socket.getInputStream());
			byte[] cbuff = new byte[256];
			char[] charBuff = new char[256];
			int size = 0;
			while( (size = bufferedReader.read(cbuff))> 0) {
				convertByteToChar(cbuff, charBuff, size);
				System.out.println(charBuff);
			}
			bufferedReader.close();
			socket.close();
		}
	}
	
	private void convertByteToChar(byte[] cbuff, char[] charBuff, int size) {
		for(int i=0; i<charBuff.length; i++) {
			if(i < size) {
				charBuff[i] = (char)cbuff[i];
			} else {
				charBuff[i] = ' ';
			}
		}
		
	}

	public static void main(String[] args) {
		try {
			HelloClient client = new HelloClient(10);
			client.setupClients("localhost", 9999);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
启动10个客户端去连接服务器端,接受到服务器端问候以后客户端关闭连接。

特别提示:一定要初始化缓冲区charBuff
程序运行结果:



目录
相关文章
|
13天前
|
存储 缓存 监控
Java面试题:在Java中,对象何时可以被垃圾回收?编程中,如何更好地做好垃圾回收处理?
Java面试题:在Java中,对象何时可以被垃圾回收?编程中,如何更好地做好垃圾回收处理?
22 0
|
1天前
|
监控 Java
Java并发编程:深入理解线程池
在Java并发编程领域,线程池是提升应用性能和资源管理效率的关键工具。本文将深入探讨线程池的工作原理、核心参数配置以及使用场景,通过具体案例展示如何有效利用线程池优化多线程应用的性能。
|
12天前
|
JavaScript Java 测试技术
基于Java的智慧医疗服务平台系统设计和实现(源码+LW+部署讲解)
基于Java的智慧医疗服务平台系统设计和实现(源码+LW+部署讲解)
33 8
|
9天前
|
安全 Java 开发者
Java并发编程中的线程安全性与性能优化
在Java编程中,处理并发问题是至关重要的。本文探讨了Java中线程安全性的概念及其在性能优化中的重要性。通过深入分析多线程环境下的共享资源访问问题,结合常见的并发控制手段和性能优化技巧,帮助开发者更好地理解和应对Java程序中的并发挑战。 【7月更文挑战第14天】
|
9天前
|
监控 Java API
Java并发编程之线程池深度解析
【7月更文挑战第14天】在Java并发编程领域,线程池是提升性能、管理资源的关键工具。本文将深入探讨线程池的核心概念、内部工作原理以及如何有效使用线程池来处理并发任务,旨在为读者提供一套完整的线程池使用和优化策略。
|
12天前
|
存储 安全 算法
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第72天】 在现代软件开发中,尤其是Java应用开发领域,并发编程是一个无法回避的重要话题。随着多核处理器的普及,合理利用并发机制对于提高软件性能、响应速度和资源利用率具有重要意义。本文旨在探讨Java并发编程的核心概念、线程安全的策略以及性能优化技巧,帮助开发者构建高效且可靠的并发应用。通过实例分析和理论阐述,我们将揭示在高并发环境下如何平衡线程安全与系统性能之间的关系,并提出一系列最佳实践方法。
|
2天前
|
存储 Java 调度
Java的并行编程有哪些优势
Java的并行编程有哪些优势
|
4天前
|
算法 安全 Java
Java并发编程的艺术与实践
【7月更文挑战第19天】在Java的世界中,并发编程是提升应用性能和响应能力的关键。本文将深入探讨如何利用Java的并发工具高效地构建多线程应用程序。我们将从基础的线程管理讲起,逐步过渡到高级的并发框架,如Executors和Futures,以及最新的CompletableFuture。同时,文章还会涵盖线程安全、锁机制、同步器等关键概念,确保读者能够在实战中避免常见的并发陷阱。
13 0
|
5天前
|
Java 开发者
Java并发编程之Executor框架详解
【7月更文挑战第18天】本文旨在深入探讨Java中的Executor框架,揭示其对并发编程的优化作用。通过解析Executor接口、ThreadPoolExecutor和ScheduledExecutorService等关键组件,文章展示了如何有效管理和控制线程资源。同时,结合实例分析,本文阐释了Executor框架在提高程序性能、简化代码结构方面的实际应用价值。旨在为Java开发者提供并发编程的高级工具,帮助他们构建更加高效、稳定的多线程应用。
|
9天前
|
Java 开发者
Java并发编程中的锁机制与性能优化
【7月更文挑战第14天】本文深入探讨了Java中锁的概念、种类及其在并发编程中的应用,并分析了不同锁类型对程序性能的影响。通过实例展示了如何合理选择和使用锁来提升应用的性能,同时指出了锁使用过程中可能遇到的问题和调优策略。旨在为Java开发者提供锁机制的深入理解和性能优化的实用建议。
13 0