Java Socket編程實(shí)現(xiàn)簡(jiǎn)單的問候服務(wù)
本文實(shí)例講解了Java Socket編程實(shí)現(xiàn)簡(jiǎn)單的問候服務(wù)的詳細(xì)代碼,供大家參考,具體內(nèi)容如下
服務(wù)器端:
實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的Hello服務(wù),打印輸出客戶端IP地址到控制臺(tái),對(duì)任何連接的客戶端都會(huì)發(fā)送一串字符(Hello, Java Socket)然后關(guān)閉與客戶端連接。等待下一個(gè)客戶端的連接請(qǐng)求到來。
客戶端:
實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的Socket連接到Hello服務(wù)器端,接受服務(wù)器端發(fā)送過來的字節(jié)數(shù)據(jù)打印并輸出內(nèi)容到控制臺(tái)。
關(guān)鍵技巧:
由于JAVA中提供非常多的輸入與輸出流API,導(dǎo)致很多初學(xué)者接觸JAVA SOCKET編程時(shí),由于對(duì)網(wǎng)絡(luò)字節(jié)通信的本質(zhì)缺乏了解,直接一個(gè)readline()去接受Socket字節(jié)流。但是由于發(fā)送一方并沒有發(fā)送/r/n導(dǎo)致一直無法讀到數(shù)據(jù),這個(gè)是最常見的一個(gè)錯(cuò)誤。另外一些常見的錯(cuò)誤包括沒有初始化接受緩沖區(qū)導(dǎo)致字符亂碼,沒有按照讀入接受到字節(jié)數(shù)重新組裝,導(dǎo)致接受到的數(shù)據(jù)異常。所以代碼演示了什么叫按字節(jié)發(fā)送與按字節(jié)接受,這個(gè)是網(wǎng)絡(luò)編程中非常重要的概念與原則。讓那些輸入流println()方法與輸出流readline()方法見鬼去吧,不是不好用,而是我建議你不要用,因?yàn)槟切?huì)妨礙你的網(wǎng)絡(luò)編程本質(zhì)的認(rèn)識(shí)與理解。另外我要特別說明一下:有時(shí)候flush()真的不是必須的除非你使用了帶有緩沖的輸入與輸出流來讀寫字節(jié)。
服務(wù)器端代碼:
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();
}
}
}
服務(wù)器在端口9999監(jiān)聽并等待連接,使用Java Thread來實(shí)現(xiàn)服務(wù)器端啟動(dòng)。
客戶端代碼如下:
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();
}
}
}
啟動(dòng)10個(gè)客戶端去連接服務(wù)器端,接受到服務(wù)器端問候以后客戶端關(guān)閉連接。
特別提示:一定要初始化緩沖區(qū)charBuff
程序運(yùn)行結(jié)果:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。
- Java字符流與字節(jié)流區(qū)別與用法分析
- 詳解Java中字符流與字節(jié)流的區(qū)別
- Java編程中字節(jié)流與字符流IO操作示例
- 深入解析Java編程中面向字節(jié)流的一些應(yīng)用
- java基于Socket做一個(gè)簡(jiǎn)單下載器
- java使用Socket實(shí)現(xiàn)SMTP協(xié)議發(fā)送郵件
- java Socket實(shí)現(xiàn)網(wǎng)頁版在線聊天
- java實(shí)現(xiàn)一個(gè)簡(jiǎn)單TCPSocket聊天室功能分享
- Java基于Socket實(shí)現(xiàn)HTTP下載客戶端
- Java socket字節(jié)流傳輸示例解析
相關(guān)文章
Java獲取漢字拼音的全拼和首拼實(shí)現(xiàn)代碼分享
這篇文章主要介紹了Java獲取漢字拼音的全拼和首拼實(shí)現(xiàn)代碼分享,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-06-06
springboot使用redis對(duì)單個(gè)對(duì)象進(jìn)行自動(dòng)緩存更新刪除的實(shí)現(xiàn)
本文主要介紹了springboot使用redis對(duì)單個(gè)對(duì)象進(jìn)行自動(dòng)緩存更新刪除的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
Java網(wǎng)絡(luò)通信中ServerSocket的設(shè)計(jì)優(yōu)化方案
今天小編就為大家分享一篇關(guān)于Java網(wǎng)絡(luò)通信中ServerSocket的設(shè)計(jì)優(yōu)化方案,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-04-04
Spring如何基于xml實(shí)現(xiàn)聲明式事務(wù)控制
這篇文章主要介紹了Spring如何基于xml實(shí)現(xiàn)聲明式事務(wù)控制,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
詳解Spring Security的Web應(yīng)用和指紋登錄實(shí)踐
這篇文章主要介紹了詳解Spring Security的Web應(yīng)用和指紋登錄實(shí)踐,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03
SpringMvc向request域中設(shè)置數(shù)據(jù)的方法
這篇文章主要介紹了SpringMvc向request域中設(shè)置數(shù)據(jù)的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09

