Java中的網(wǎng)絡(luò)編程

Transmission Control Protocol/Internet Protocol的簡(jiǎn)寫湿镀,中譯名為傳輸控制協(xié)議/因特網(wǎng)互聯(lián)協(xié)議厅贪,又名網(wǎng)絡(luò)通訊協(xié)議北专,是Internet最基本的協(xié)議、Internet國(guó)際互聯(lián)網(wǎng)絡(luò)的基礎(chǔ)琴许,由網(wǎng)絡(luò)層的IP協(xié)議和傳輸層的TCP協(xié)議組成聋涨。TCP/IP 定義了電子設(shè)備如何連入因特網(wǎng)御板,以及數(shù)據(jù)如何在它們之間傳輸?shù)臉?biāo)準(zhǔn)。協(xié)議采用了4層的層級(jí)結(jié)構(gòu)牛郑,每一層都呼叫它的下一層所提供的協(xié)議來完成自己的需求怠肋。通俗而言:TCP負(fù)責(zé)發(fā)現(xiàn)傳輸?shù)膯栴},一有問題就發(fā)出信號(hào)淹朋,要求重新傳輸笙各,直到所有數(shù)據(jù)安全正確地傳輸?shù)侥康牡亍6鳬P是給因特網(wǎng)的每一臺(tái)聯(lián)網(wǎng)設(shè)備規(guī)定一個(gè)地址础芍。

通俗的說TCP/IP就是一些列的網(wǎng)絡(luò)通訊規(guī)則杈抢。

在TCP/IP參考模型中,將網(wǎng)絡(luò)分為以下幾層:

應(yīng)用層
傳輸層
網(wǎng)際層
主機(jī)至網(wǎng)絡(luò)層

而java中的網(wǎng)絡(luò)編程一般是在傳輸層仑性,而其他情況下都是在應(yīng)用層進(jìn)行開發(fā)(如java web/android的App開發(fā)等等)

網(wǎng)絡(luò)通訊要素

IP地址:InetAddress

-網(wǎng)絡(luò)中設(shè)備的標(biāo)識(shí)
-不易記憶惶楼,可用主機(jī)名
-本地回環(huán)地址:127.0.0.1 主機(jī)名:localhost

端口號(hào)

-用于標(biāo)識(shí)進(jìn)程的邏輯地址,不同進(jìn)程的標(biāo)識(shí)
-有效端口:0~65535诊杆,其中0~1024系統(tǒng)使用或保留端口歼捐。

傳輸協(xié)議

-通訊的規(guī)則
-常見協(xié)議:TCP,UDP

class IPDemo {
    public static void main(String[] args) throws Exception {
        // 返回本機(jī)主機(jī)名
        // InetAddress i = InetAddress.getLocalHost();

        // System.out.println(i.toString());
        // System.out.println("address:"+i.getHostAddress());
        // System.out.println("name:"+i.getHostName());

        InetAddress ia = InetAddress.getByName("thinkpad-sl400");
        System.out.println("address:" + ia.getHostAddress());
        System.out.println("name:" + ia.getHostName());

    }
}

UDP與TCP

UDP的特點(diǎn)

- 將數(shù)據(jù)及源和目的封裝成數(shù)據(jù)包中晨汹,不需要建立連接

- 每個(gè)數(shù)據(jù)報(bào)的大小在限制在64k內(nèi)

- 因無連接豹储,是不可靠協(xié)議

- 不需要建立連接,速度快

面向無連接淘这,不管對(duì)方在不在都會(huì)發(fā)送數(shù)據(jù)剥扣,而且數(shù)據(jù)容易丟失

TCP的特點(diǎn):

建立連接,形成傳輸數(shù)據(jù)的通道铝穷。

在連接中進(jìn)行大數(shù)據(jù)量傳輸

通過三次握手完成連接钠怯,是可靠協(xié)議

必須建立連接,效率會(huì)稍低

Socket

Socket就是為網(wǎng)絡(luò)服務(wù)提供的一種機(jī)制曙聂。

通信的兩端都有Socket晦炊。

網(wǎng)絡(luò)通信其實(shí)就是Socket間的通信。

數(shù)據(jù)在兩個(gè)Socket間通過IO傳輸。

UDP傳輸?shù)氖褂茫?/h3>
1刽锤、DatagramSocket與DatagramPacket

2、建立發(fā)送端朦佩,接收端并思。

3、建立數(shù)據(jù)包语稠。

4宋彼、調(diào)用Socket的發(fā)送接收方法。

5仙畦、關(guān)閉Socket输涕。
發(fā)送端與接收端是兩個(gè)獨(dú)立的運(yùn)行程序

UDP的使用Demo1:

需求:通過udp傳輸方式,將一段文字?jǐn)?shù)據(jù)發(fā)送出去慨畸。莱坎,
定義一個(gè)udp發(fā)送端。
思路:
1寸士,建立updsocket服務(wù)檐什。
2,提供數(shù)據(jù)弱卡,并將數(shù)據(jù)封裝到數(shù)據(jù)包中乃正。
3,通過socket服務(wù)的發(fā)送功能婶博,將數(shù)據(jù)包發(fā)出去瓮具。
4,關(guān)閉資源凡人。

代碼如下:

class UdpSend {
    public static void main(String[] args) throws Exception {
        // 1名党,創(chuàng)建udp服務(wù)。通過DatagramSocket對(duì)象挠轴。
        DatagramSocket ds = new DatagramSocket(8888);

        // 2兑巾,確定數(shù)據(jù),并封裝成數(shù)據(jù)包忠荞。DatagramPacket(byte[] buf, int length, InetAddress
        // address, int port)

        byte[] buf = "udp ge men lai le ".getBytes();
        DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.254"), 10000);

        // 3蒋歌,通過socket服務(wù),將已有的數(shù)據(jù)包發(fā)送出去委煤。通過send方法堂油。
        ds.send(dp);

        // 4,關(guān)閉資源碧绞。

        ds.close();

    }
}

/*
 * 需求: 定義一個(gè)應(yīng)用程序府框,用于接收udp協(xié)議傳輸?shù)臄?shù)據(jù)并處理的。
 * 定義udp的接收端讥邻。 思路: 1迫靖,定義udpsocket服務(wù)院峡。通常會(huì)監(jiān)聽一個(gè)端口。其實(shí)就是給這個(gè)接收網(wǎng)絡(luò)應(yīng)用程序定義數(shù)字標(biāo)識(shí)系宜。
 * 方便于明確哪些數(shù)據(jù)過來該應(yīng)用程序可以處理照激。
 * 2,定義一個(gè)數(shù)據(jù)包盹牧,因?yàn)橐鎯?chǔ)接收到的字節(jié)數(shù)據(jù)俩垃。 因?yàn)閿?shù)據(jù)包對(duì)象中有更多功能可以提取字節(jié)數(shù)據(jù)中的不同數(shù)據(jù)信息。
 * 3汰寓,通過socket服務(wù)的receive方法將收到的數(shù)據(jù)存入已定義好的數(shù)據(jù)包中口柳。 4,通過數(shù)據(jù)包對(duì)象的特有功能有滑。將這些不同的數(shù)據(jù)取出跃闹。打印在控制臺(tái)上。
 * 5毛好,關(guān)閉資源辣卒。
 */

class UdpRece {
    public static void main(String[] args) throws Exception {
        // 1,創(chuàng)建udp socket,建立端點(diǎn)睛榄。
        DatagramSocket ds = new DatagramSocket(10000);
        while (true) {
            // 2,定義數(shù)據(jù)包荣茫。用于存儲(chǔ)數(shù)據(jù)。
            byte[] buf = new byte[1024];
            DatagramPacket dp = new DatagramPacket(buf, buf.length);

            // 3场靴,通過服務(wù)的receive方法將收到數(shù)據(jù)存入數(shù)據(jù)包中啡莉。
            ds.receive(dp);// 阻塞式方法。

            // 4旨剥,通過數(shù)據(jù)包的方法獲取其中的數(shù)據(jù)咧欣。
            String ip = dp.getAddress().getHostAddress();

            String data = new String(dp.getData(), 0, dp.getLength());

            int port = dp.getPort();

            System.out.println(ip + "::" + data + "::" + port);

        }
        // 5,關(guān)閉資源
        // ds.close();

    }
}

建議的UDP聊天工具:

/*
 * 編寫一個(gè)聊天程序轨帜。 有收數(shù)據(jù)的部分魄咕,和發(fā)數(shù)據(jù)的部分。 這兩部分需要同時(shí)執(zhí)行蚌父。 那就需要用到多線程技術(shù)哮兰。 一個(gè)線程控制收,一個(gè)線程控制發(fā)苟弛。
 * 因?yàn)槭蘸桶l(fā)動(dòng)作是不一致的喝滞,所以要定義兩個(gè)run方法。 而且這兩個(gè)方法要封裝到不同的類中膏秫。
 */
import java.io.*;
import java.net.*;

class Send implements Runnable {
    private DatagramSocket ds;

    public Send(DatagramSocket ds) {
        this.ds = ds;
    }

    public void run() {
        try {
            BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

            String line = null;

            while ((line = bufr.readLine()) != null) {

                byte[] buf = line.getBytes();

                DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.255"), 10002);

                ds.send(dp);

                if ("886".equals(line))
                    break;
            }
        } catch (Exception e) {
            throw new RuntimeException("發(fā)送端失敗");
        }
    }
}

class Rece implements Runnable {

    private DatagramSocket ds;

    public Rece(DatagramSocket ds) {
        this.ds = ds;
    }

    public void run() {
        try {
            while (true) {
                byte[] buf = new byte[1024];
                DatagramPacket dp = new DatagramPacket(buf, buf.length);

                ds.receive(dp);

                String ip = dp.getAddress().getHostAddress();

                String data = new String(dp.getData(), 0, dp.getLength());

                if ("886".equals(data)) {
                    System.out.println(ip + "....離開聊天室");
                    break;
                }

                System.out.println(ip + ":" + data);
            }
        } catch (Exception e) {
            throw new RuntimeException("接收端失敗");
        }
    }
}

class ChatDemo {
    public static void main(String[] args) throws Exception {
        DatagramSocket sendSocket = new DatagramSocket();
        DatagramSocket receSocket = new DatagramSocket(10002);

        new Thread(new Send(sendSocket)).start();
        new Thread(new Rece(receSocket)).start();

    }
}

TCP的使用

1右遭、Socket和ServerSocket

2、建立客戶端和服務(wù)器端

3、建立連接后窘哈,通過Socket中的IO流進(jìn)行數(shù)據(jù)的傳輸

4吹榴、關(guān)閉socket

同樣,客戶端與服務(wù)器端是兩個(gè)獨(dú)立的應(yīng)用程序滚婉。

TCP鏈接可以用三次握手兩次揮手來形容图筹。

TCP使用Demo1:

/*
 * 演示tcp傳輸。
 * 1,tcp分客戶端和服務(wù)端满哪。 2婿斥,客戶端對(duì)應(yīng)的對(duì)象是Socket劝篷。 服務(wù)端對(duì)應(yīng)的對(duì)象是ServerSocket哨鸭。
 */

/*
 * 客戶端, 通過查閱socket對(duì)象娇妓,發(fā)現(xiàn)在該對(duì)象建立時(shí)像鸡,就可以去連接指定主機(jī)。 因?yàn)閠cp是面向連接的哈恰。所以在建立socket服務(wù)時(shí)只估,
 * 就要有服務(wù)端存在,并連接成功着绷。形成通路后蛔钙,在該通道進(jìn)行數(shù)據(jù)的傳輸荠医。
 * 需求:給服務(wù)端發(fā)送給一個(gè)文本數(shù)據(jù)吁脱。
 * 步驟: 1,創(chuàng)建Socket服務(wù)彬向。并指定要連接的主機(jī)和端口兼贡。
 * 
 */
import java.io.*;
import java.net.*;

class TcpClient {
    public static void main(String[] args) throws Exception {
        // 創(chuàng)建客戶端的socket服務(wù)。指定目的主機(jī)和端口
        Socket s = new Socket("192.168.1.254", 10003);

        // 為了發(fā)送數(shù)據(jù)娃胆,應(yīng)該獲取socket流中的輸出流遍希。
        OutputStream out = s.getOutputStream();

        out.write("tcp ge men lai le ".getBytes());

        s.close();
    }
}

/*
 * 需求:定義端點(diǎn)接收數(shù)據(jù)并打印在控制臺(tái)上。
 * 服務(wù)端: 1里烦,建立服務(wù)端的socket服務(wù)凿蒜。ServerSocket(); 并監(jiān)聽一個(gè)端口。 2胁黑,獲取連接過來的客戶端對(duì)象篙程。
 * 通過ServerSokcet的 accept方法。沒有連接就會(huì)等别厘,所以這個(gè)方法阻塞式的虱饿。
 * 3,客戶端如果發(fā)過來數(shù)據(jù),那么服務(wù)端要使用對(duì)應(yīng)的客戶端對(duì)象氮发,并獲取到該客戶端對(duì)象的讀取流來讀取發(fā)過來的數(shù)據(jù)渴肉。 并打印在控制臺(tái)。
 * 4爽冕,關(guān)閉服務(wù)端仇祭。(可選)
 */
class TcpServer {
    public static void main(String[] args) throws Exception {
        // 建立服務(wù)端socket服務(wù)。并監(jiān)聽一個(gè)端口颈畸。
        ServerSocket ss = new ServerSocket(10003);

        // 通過accept方法獲取連接過來的客戶端對(duì)象乌奇。
        while (true) {
            Socket s = ss.accept();

            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip + ".....connected");

            // 獲取客戶端發(fā)送過來的數(shù)據(jù),那么要使用客戶端對(duì)象的讀取流來讀取數(shù)據(jù)眯娱。
            InputStream in = s.getInputStream();

            byte[] buf = new byte[1024];
            int len = in.read(buf);

            System.out.println(new String(buf, 0, len));

            s.close();// 關(guān)閉客戶端.
        }
        // ss.close();
    }
}

TCP使用demo2:

import java.io.*;
import java.net.*;
/*
 * 演示tcp的傳輸?shù)目蛻舳撕头?wù)端的互訪礁苗。
 * 需求:客戶端給服務(wù)端發(fā)送數(shù)據(jù),服務(wù)端收到后徙缴,給客戶端反饋信息试伙。
 */

/*
 * 客戶端: 1,建立socket服務(wù)于样。指定要連接主機(jī)和端口疏叨。 2,獲取socket流中的輸出流穿剖。將數(shù)據(jù)寫到該流中蚤蔓。通過網(wǎng)絡(luò)發(fā)送給服務(wù)端。
 * 3糊余,獲取socket流中的輸入流秀又,將服務(wù)端反饋的數(shù)據(jù)獲取到,并打印啄刹。 4涮坐,關(guān)閉客戶端資源。
 * 
 */
class TcpClient2 {
    public static void main(String[] args) throws Exception {
        Socket s = new Socket("192.168.1.254", 10004);

        OutputStream out = s.getOutputStream();

        out.write("服務(wù)端誓军,你好".getBytes());

        InputStream in = s.getInputStream();

        byte[] buf = new byte[1024];

        int len = in.read(buf);

        System.out.println(new String(buf, 0, len));

        s.close();
    }
}

class TcpServer2 {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(10004);

        Socket s = ss.accept();

        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "....connected");
        InputStream in = s.getInputStream();

        byte[] buf = new byte[1024];

        int len = in.read(buf);

        System.out.println(new String(buf, 0, len));

        OutputStream out = s.getOutputStream();

        Thread.sleep(10000);
        out.write("哥們收到,你也好".getBytes());

        s.close();

        ss.close();
    }
}

TCP使用Demo3:

/*
 * 需求:建立一個(gè)文本轉(zhuǎn)換服務(wù)器袱讹。 客戶端給服務(wù)端發(fā)送文本,服務(wù)單會(huì)將文本轉(zhuǎn)成大寫在返回給客戶端昵时。
 * 而且客戶度可以不斷的進(jìn)行文本轉(zhuǎn)換捷雕。當(dāng)客戶端輸入over時(shí),轉(zhuǎn)換結(jié)束壹甥。
 * 分析: 客戶端: 既然是操作設(shè)備上的數(shù)據(jù)救巷,那么就可以使用io技術(shù),并按照io的操作規(guī)律來思考句柠。 源:鍵盤錄入浦译。 目的:網(wǎng)絡(luò)設(shè)備棒假,網(wǎng)絡(luò)輸出流。
 * 而且操作的是文本數(shù)據(jù)精盅∶毖疲可以選擇字符流。
 * 步驟 1叹俏,建立服務(wù)妻枕。 2,獲取鍵盤錄入粘驰。 3屡谐,將數(shù)據(jù)發(fā)給服務(wù)端。 4蝌数,后去服務(wù)端返回的大寫數(shù)據(jù)愕掏。 5,結(jié)束籽前,關(guān)資源亭珍。
 * 都是文本數(shù)據(jù)敷钾,可以使用字符流進(jìn)行操作枝哄,同時(shí)提高效率,加入緩沖阻荒。
 */
import java.io.*;
import java.net.*;

class TransClient {
    public static void main(String[] args) throws Exception {
        Socket s = new Socket("192.168.1.254", 10005);

        // 定義讀取鍵盤數(shù)據(jù)的流對(duì)象挠锥。
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

        // 定義目的,將數(shù)據(jù)寫入到socket輸出流侨赡。發(fā)給服務(wù)端蓖租。
        // BufferedWriter bufOut =
        // new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        PrintWriter out = new PrintWriter(s.getOutputStream(), true);

        // 定義一個(gè)socket讀取流,讀取服務(wù)端返回的大寫信息羊壹。
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String line = null;

        while ((line = bufr.readLine()) != null) {
            if ("over".equals(line))
                break;

            out.println(line);
            // bufOut.write(line);
            // bufOut.newLine();
            // bufOut.flush();

            String str = bufIn.readLine();
            System.out.println("server:" + str);

        }

        bufr.close();
        s.close();

    }
}

/*
 * 服務(wù)端: 源:socket讀取流蓖宦。 目的:socket輸出流。 都是文本油猫,裝飾稠茂。
 */
class TransServer {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(10005);

        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "....connected");

        // 讀取socket讀取流中的數(shù)據(jù)沫浆。
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        // 目的哄辣。socket輸出流。將大寫數(shù)據(jù)寫入到socket輸出流窑滞,并發(fā)送給客戶端毡证。
        // BufferedWriter bufOut =
        // new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

        PrintWriter out = new PrintWriter(s.getOutputStream(), true);

        String line = null;
        while ((line = bufIn.readLine()) != null) {

            System.out.println(line);

            out.println(line.toUpperCase());
            // bufOut.write(line.toUpperCase());
            // bufOut.newLine();
            // bufOut.flush();
        }

        s.close();
        ss.close();

    }
}

TCP使用Demo4电爹,上傳文本:

import java.io.*;
import java.net.*;

class TextClient {
    public static void main(String[] args) throws Exception {
        Socket s = new Socket("192.168.1.254", 10006);

        BufferedReader bufr = new BufferedReader(new FileReader("IPDemo.java"));

        PrintWriter out = new PrintWriter(s.getOutputStream(), true);

        String line = null;
        while ((line = bufr.readLine()) != null) {
            out.println(line);
        }

        s.shutdownOutput();// 關(guān)閉客戶端的輸出流。相當(dāng)于給流中加入一個(gè)結(jié)束標(biāo)記-1.

        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String str = bufIn.readLine();
        System.out.println(str);

        bufr.close();

        s.close();
    }
}

class TextServer {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(10006);

        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "....connected");

        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        PrintWriter out = new PrintWriter(new FileWriter("server.txt"), true);

        String line = null;

        while ((line = bufIn.readLine()) != null) {
            // if("over".equals(line))
            // break;
            out.println(line);
        }

        PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
        pw.println("上傳成功");

        out.close();
        s.close();
        ss.close();

    }
}

TCP使用之上傳圖片

/*
 * 需求:上傳圖片料睛。
 */

/*
 * 客戶端丐箩。 
 * 1摇邦,服務(wù)端點(diǎn)。 
 * 2屎勘,讀取客戶端已有的圖片數(shù)據(jù)涎嚼。 
 * 3,通過socket 輸出流將數(shù)據(jù)發(fā)給服務(wù)端挑秉。 
 * 4法梯,讀取服務(wù)端反饋信息。 
 * 5犀概,關(guān)閉立哑。
 */

import java.io.*;
import java.net.*;

class PicClient {
    public static void main(String[] args) throws Exception {
        Socket s = new Socket("192.168.1.254", 10007);

        FileInputStream fis = new FileInputStream("c:\\1.bmp");

        OutputStream out = s.getOutputStream();

        byte[] buf = new byte[1024];

        int len = 0;

        while ((len = fis.read(buf)) != -1) {
            out.write(buf, 0, len);
        }

        // 告訴服務(wù)端數(shù)據(jù)已寫完
        s.shutdownOutput();

        InputStream in = s.getInputStream();

        byte[] bufIn = new byte[1024];

        int num = in.read(bufIn);
        System.out.println(new String(bufIn, 0, num));

        fis.close();
        s.close();
    }
}

/*
 * 服務(wù)端
 */
class PicServer {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(10007);

        Socket s = ss.accept();

        InputStream in = s.getInputStream();

        FileOutputStream fos = new FileOutputStream("server.bmp");

        byte[] buf = new byte[1024];

        int len = 0;
        while ((len = in.read(buf)) != -1) {
            fos.write(buf, 0, len);
        }

        OutputStream out = s.getOutputStream();

        out.write("上傳成功".getBytes());

        fos.close();

        s.close();

        ss.close();
    }
}

TCP之多線程上傳圖片

/*
 * 需求:上傳圖片。
 */
/*
 * 客戶端姻灶。
 *  1铛绰,服務(wù)端點(diǎn)。
 *  2产喉,讀取客戶端已有的圖片數(shù)據(jù)捂掰。 
 *  3,通過socket 輸出流將數(shù)據(jù)發(fā)給服務(wù)端曾沈。
 *  4这嚣,讀取服務(wù)端反饋信息。 
 *  5塞俱,關(guān)閉姐帚。
 * 
 */

import java.io.*;
import java.net.*;

class PicClient {
    public static void main(String[] args) throws Exception {
        if (args.length != 1) {
            System.out.println("請(qǐng)選擇一個(gè)jpg格式的圖片");
            return;
        }

        File file = new File(args[0]);
        if (!(file.exists() && file.isFile())) {
            System.out.println("該文件有問題,要么補(bǔ)存在障涯,要么不是文件");
            return;

        }

        if (!file.getName().endsWith(".jpg")) {
            System.out.println("圖片格式錯(cuò)誤,請(qǐng)重新選擇");
            return;
        }

        if (file.length() > 1024 * 1024 * 5) {
            System.out.println("文件過大罐旗,沒安好心");
            return;
        }

        Socket s = new Socket("192.168.1.254", 10007);

        FileInputStream fis = new FileInputStream(file);

        OutputStream out = s.getOutputStream();

        byte[] buf = new byte[1024];

        int len = 0;

        while ((len = fis.read(buf)) != -1) {
            out.write(buf, 0, len);
        }

        // 告訴服務(wù)端數(shù)據(jù)已寫完
        s.shutdownOutput();

        InputStream in = s.getInputStream();

        byte[] bufIn = new byte[1024];

        int num = in.read(bufIn);
        System.out.println(new String(bufIn, 0, num));

        fis.close();
        s.close();
    }
}

/*
 * 服務(wù)端
 * 
 * 這個(gè)服務(wù)端有個(gè)局限性。當(dāng)A客戶端連接上以后唯蝶。被服務(wù)端獲取到九秀。服務(wù)端執(zhí)行具體流程。 這時(shí)B客戶端連接粘我,只有等待鼓蜒。
 * 因?yàn)榉?wù)端還沒有處理完A客戶端的請(qǐng)求,還有循環(huán)回來執(zhí)行下次accept方法涂滴。所以 暫時(shí)獲取不到B客戶端對(duì)象友酱。
 * 那么為了可以讓多個(gè)客戶端同時(shí)并發(fā)訪問服務(wù)端。 那么服務(wù)端最好就是將每個(gè)客戶端封裝到一個(gè)單獨(dú)的線程中柔纵,這樣缔杉,就可以同時(shí)處理多個(gè)客戶端請(qǐng)求。
 * 如何定義線程呢搁料?
 * 
 * 只要明確了每一個(gè)客戶端要在服務(wù)端執(zhí)行的代碼即可或详。將該代碼存入run方法中系羞。
 */

class PicThread implements Runnable {

    private Socket s;

    PicThread(Socket s) {
        this.s = s;
    }

    public void run() {

        int count = 1;
        String ip = s.getInetAddress().getHostAddress();
        try {
            System.out.println(ip + "....connected");

            InputStream in = s.getInputStream();

            File dir = new File("d:\\pic");

            File file = new File(dir, ip + "(" + (count) + ")" + ".jpg");

            while (file.exists())
                file = new File(dir, ip + "(" + (count++) + ")" + ".jpg");

            FileOutputStream fos = new FileOutputStream(file);

            byte[] buf = new byte[1024];

            int len = 0;
            while ((len = in.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }

            OutputStream out = s.getOutputStream();

            out.write("上傳成功".getBytes());

            fos.close();

            s.close();
        } catch (Exception e) {
            throw new RuntimeException(ip + "上傳失敗");
        }
    }
}

class PicServer {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(10007);

        while (true) {
            Socket s = ss.accept();

            new Thread(new PicThread(s)).start();
        }

        // ss.close();
    }
}

TCP使用之并發(fā)登陸

/*
 * 客戶端通過鍵盤錄入用戶名。 服務(wù)端對(duì)這個(gè)用戶名進(jìn)行校驗(yàn)霸琴。
 * 如果該用戶存在椒振,在服務(wù)端顯示xxx,已登陸梧乘。 并在客戶端顯示 xxx澎迎,歡迎光臨。
 * 如果該用戶存在选调,在服務(wù)端顯示xxx夹供,嘗試登陸。 并在客戶端顯示 xxx仁堪,該用戶不存在哮洽。
 * 最多就登錄三次。
 */
import java.io.*;
import java.net.*;

class LoginClient {
    public static void main(String[] args) throws Exception {
        Socket s = new Socket("192.168.1.254", 10008);

        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

        PrintWriter out = new PrintWriter(s.getOutputStream(), true);

        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        for (int x = 0; x < 3; x++) {
            String line = bufr.readLine();
            if (line == null)
                break;
            out.println(line);

            String info = bufIn.readLine();
            System.out.println("info:" + info);
            if (info.contains("歡迎"))
                break;

        }

        bufr.close();
        s.close();
    }
}

class UserThread implements Runnable {
    private Socket s;

    UserThread(Socket s) {
        this.s = s;
    }

    public void run() {
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "....connected");
        try {
            for (int x = 0; x < 3; x++) {
                BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

                String name = bufIn.readLine();
                if (name == null)
                    break;

                BufferedReader bufr = new BufferedReader(new FileReader("user.txt"));

                PrintWriter out = new PrintWriter(s.getOutputStream(), true);

                String line = null;

                boolean flag = false;
                while ((line = bufr.readLine()) != null) {
                    if (line.equals(name)) {
                        flag = true;
                        break;
                    }
                }

                if (flag) {
                    System.out.println(name + ",已登錄");
                    out.println(name + ",歡迎光臨");
                    break;
                } else {
                    System.out.println(name + ",嘗試登錄");
                    out.println(name + ",用戶名不存在");
                }

            }
            s.close();
        } catch (Exception e) {
            throw new RuntimeException(ip + "校驗(yàn)失敗");
        }
    }
}

class LoginServer {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(10008);

        while (true) {
            Socket s = ss.accept();

            new Thread(new UserThread(s)).start();
        }
    }
}    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弦聂,一起剝皮案震驚了整個(gè)濱河市鸟辅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌莺葫,老刑警劉巖匪凉,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異徙融,居然都是意外死亡洒缀,警方通過查閱死者的電腦和手機(jī)瑰谜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門欺冀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人萨脑,你說我怎么就攤上這事隐轩。” “怎么了渤早?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵职车,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我鹊杖,道長(zhǎng)悴灵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任骂蓖,我火速辦了婚禮积瞒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘登下。我一直安慰自己茫孔,他們只是感情好叮喳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缰贝,像睡著了一般馍悟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剩晴,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天锣咒,我揣著相機(jī)與錄音,去河邊找鬼赞弥。 笑死宠哄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嗤攻。 我是一名探鬼主播毛嫉,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼妇菱!你這毒婦竟也來了承粤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤闯团,失蹤者是張志新(化名)和其女友劉穎辛臊,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體房交,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡彻舰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了候味。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刃唤。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖白群,靈堂內(nèi)的尸體忽然破棺而出尚胞,到底是詐尸還是另有隱情,我是刑警寧澤帜慢,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布笼裳,位于F島的核電站,受9級(jí)特大地震影響粱玲,放射性物質(zhì)發(fā)生泄漏躬柬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一抽减、第九天 我趴在偏房一處隱蔽的房頂上張望允青。 院中可真熱鬧,春花似錦胯甩、人聲如沸昧廷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)木柬。三九已至皆串,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間眉枕,已是汗流浹背恶复。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留速挑,地道東北人谤牡。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像姥宝,于是被迫代替她去往敵國(guó)和親翅萤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Java中的網(wǎng)絡(luò)編程 Transmission Control Protocol/Internet Protoco...
    寶塔山上的貓閱讀 262評(píng)論 0 0
  • 網(wǎng)絡(luò)概念第一天 兩臺(tái)電腦怎么通過網(wǎng)絡(luò)傳輸數(shù)據(jù)腊满?怎樣才能知道傳輸?shù)氖菙?shù)據(jù)套么?誰摸過網(wǎng)線? 看電影碳蛋,怎么看的胚泌?通過電流,...
    小吖朱閱讀 1,555評(píng)論 0 1
  • 1. 網(wǎng)絡(luò)編程概述 1.1 計(jì)算機(jī)網(wǎng)絡(luò) 是指將地理位置不同的具有獨(dú)立功能的多臺(tái)計(jì)算機(jī)及其外部設(shè)備肃弟,通過通信線路連接...
    JackChen1024閱讀 1,037評(píng)論 0 3
  • 01 我記得 那是花紅柳綠的季節(jié) 在校園的農(nóng)場(chǎng)里 我們盡情奔跑 放飛夢(mèng)想 手里的魚線一圈圈減少 空中的風(fēng)箏越飛越高...
    王木木勿忘初心閱讀 225評(píng)論 0 1
  • 在夜涼如水的萍水畔 我和愛的人在這里相會(huì) 我的心里的激動(dòng)逃避不了 她溫柔的言語(yǔ)令我心醉 她說今晚的夜色多么美好 我...
    過路的蜻蜓閱讀 224評(píng)論 0 3