公告版位
需要找什麼嗎? 左邊分類或許可以幫助你...

Server :

 package javaapplication2;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class MyServer {

    public static int onlineCount = 0;

    MyServer() {
        new Thread() {

            public void run() {
                while (true) {
                    try {
                        System.err.println("目前線上人數:" + onlineCount);
                        Thread.sleep(1000);
                    } catch (Exception e) {
                    }
                }
            }
        }.start();
    }

    public static void main(String[] args) throws Exception {
        new MyServer();

        ServerSocket ss = new ServerSocket(80);
        System.out.println("伺服器已啟動...");

        while (true) {
            Socket s = ss.accept();
            Thread t = new Thread(new MyThread(s));
            t.start();
        }
    }
}

class MyThread extends Thread {

    Socket s;

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

    @Override
    public void run() {
        MyServer.onlineCount++;
        try {
            System.out.println(s.getRemoteSocketAddress() + " 已連線...");
            BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream()));
            PrintWriter w = new PrintWriter(new OutputStreamWriter(s.getOutputStream()), true);

            while (true) {
                w.println("你好...我是伺服器,這是伺服器的訊息");
                System.out.println(s.getRemoteSocketAddress() + " 傳遞的訊息是:" + r.readLine());
            }


        } catch (Exception e) {
            System.err.println(s.getRemoteSocketAddress() + " 已離線");
        }
        MyServer.onlineCount--;
    }
}

Client

package javaapplication2;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

public class Client {

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread() {

                public void run() {
                    try {
                        Socket s = new Socket(InetAddress.getByName("163.15.202.74"), 1024);
                        BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream()));
                        PrintWriter w = new PrintWriter(new OutputStreamWriter(s.getOutputStream()), true);

                        w.println("你好...我是客戶端");
                        System.out.println("從伺服器傳來的資料:" + r.readLine());

                        while (true) {
                        }
                    } catch (Exception e) {
                    }
                }
            }.start();
        }

    }
}

黃彥霖 發表在 痞客邦 留言(0) 人氣()

ServerSocket ss = new ServerSocket(1024);
System.out.println("伺服器啟動於 : " + ss.getInetAddress().getHostAddress());

 

輸出結果:

伺服器啟動於 : 61.227.71.237:5555


黃彥霖 發表在 痞客邦 留言(0) 人氣()

取得 客戶端 IP:Port

String ipPort = clientSocket.getRemoteSocketAddress().toString().split("/")[1];

取得客戶端 IP

String ip = clientSocket.getInetAddress().toString().split("/")[1];

 

//以上的 clientSocket 你必須先建立 Socket 物件才可以使用。

 

解說:

JAVA 取得IP時都會自動加上斜線,此程式碼使用 split() 來把斜線消除

如1 : /127.0.0.1:8080 消除後會變成 127.0.0.1:8080

黃彥霖 發表在 痞客邦 留言(2) 人氣()

    依造個人需求,在使用TCP設計客戶端(Client)時,有時候使用Socket方便;有時候使用TcpClient方便。所以今天我提供2種常使用與容易使用的方式,且不需要事先宣告byte[]來當作緩衝(Buffer),也不需要用迴圈把byte一個一個讀取出來。如此一來可以專心在商業邏輯上,加快程式的選寫速度與維護。

方法一 使用 Socket:

using System;
using System.Net;
using System.Net.Sockets;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socket.Connect("61.227.71.237", 1024); // 1.設定 IP:Port 2.連線至伺服器
        NetworkStream stream = new NetworkStream(socket);
        StreamReader sr = new StreamReader(stream);
        StreamWriter sw = new StreamWriter(stream);
        
        sw.WriteLine("你好伺服器,我是客戶端。"); // 將資料寫入緩衝
        sw.Flush(); // 刷新緩衝並將資料上傳到伺服器

        Console.WriteLine("從伺服器接收的資料: " + sr.ReadLine());
        
        Console.ReadLine();
    }
}

方法二 使用 TcpClient :

using System;
using System.Net;
using System.Net.Sockets;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        TcpClient tcp = new TcpClient("61.227.71.237", 1024); // 1.設定 IP:Port 2.連線至伺服器
        NetworkStream stream = new NetworkStream(tcp.Client);
        StreamReader sr = new StreamReader(stream);
        StreamWriter sw = new StreamWriter(stream);

        sw.WriteLine("你好伺服器,我是客戶端。"); // 將資料寫入緩衝
        sw.Flush(); // 刷新緩衝並將資料上傳到伺服器

        Console.WriteLine("從伺服器接收的資料: " + sr.ReadLine());

        Console.ReadLine();
    }
}

 

 

 


黃彥霖 發表在 痞客邦 留言(0) 人氣()

// 本範例不適合用於對稱行網路,要解決此問題請先讓 Client 連線至 Server ,讓 Client 知道自己的 (公開/內部 IP ) 與其他人的 (公開/內部 IP ) ,再檢查自己公開 IP 是否與其他人的公開 IP 重複,如果有重複代表自己處於對稱行網路中,將使用內部 IP 進行通訊即可。

 Java 伺服器程式碼:

 

 package javaapplication1;

import java.net.*;
import java.util.ArrayList;
import java.util.HashMap;

public class JavaApplication1 {

    public static void main(String[] args) throws Exception {
        byte[] buffer = new byte[65507];
        DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
        DatagramSocket ds = new DatagramSocket(5555); // Set Server Port
        System.out.println("伺服器啟動於 : "
                + InetAddress.getLocalHost().getHostAddress() + ":" + ds.getLocalPort());
        String msg = "No Message...";
        HashMap map = new HashMap();
        while (true) {
            dp = new DatagramPacket(buffer, buffer.length);
            ds.receive(dp);
            msg = new String(dp.getData(), 0, dp.getLength());

            String ipPort = dp.getAddress().getHostAddress() + ":" + dp.getPort();
            // 只要一連線就會把 IP 放進 map 裡
            map.put(ipPort, "");
            System.out.println(ipPort + " 傳來的訊息 : " + msg);

            // 回傳他們自己的 外網IP
            dp = new DatagramPacket(ipPort.getBytes(), ipPort.length(), dp.getAddress(), dp.getPort());
            ds.send(dp);


            // 如果 2 個人上線了...
            if (map.size() == 2) {
                ArrayList a = new ArrayList();
                for (Object ip_Port : map.keySet()) {
                    a.add(ip_Port.toString());
                }
                for (Object ip_Port : map.keySet()) {
                    String temp = "";
                    for (int i = 0; i < a.size(); i++) {
                        // 如果現在這個IP不等於之前存放在 map 裡的IP
                        // 簡單來說就是只要獲取對方的IP,並不需要用到自己的IP
                        if (!a.get(i).equals(ip_Port)) {
                            temp += a.get(i);
                        }
                    }
                    // 為每個連線端發送對方的 IP:Port
                    dp = new DatagramPacket(temp.getBytes(), temp.length(), getIP(ip_Port), getPort(ip_Port));
                    ds.send(dp);
                }
            }
        }
    }

    static InetAddress getIP(Object ipPort) throws UnknownHostException {
        return InetAddress.getByName(ipPort.toString().split(":")[0]);
    }

    static int getPort(Object ipPort) {
        return Integer.valueOf(ipPort.toString().split(":")[1]);
    }
}

 

 C# 客戶端程式碼:

 

 using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;


class MyClient
{
    public static UdpClient uc = null;
    public static IPEndPoint otherIP = null;

    static void Main(string[] args)
    {
        // 伺服器的 IP 與 Port
        IPEndPoint servrIP = new IPEndPoint(IPAddress.Parse("122.121.9.25"), 5555);
        // 自訂要監聽的 Port
        IPEndPoint myIP = new IPEndPoint(IPAddress.Any, 4444);
        uc = new UdpClient(myIP.Port);
        string receive;
        byte[] b;

        // 向伺服器傳資料:
        b = System.Text.Encoding.UTF8.GetBytes("Hello Server");
        uc.Send(b, b.Length, servrIP);

        // 從伺服器取得目前電腦的IP:
        string myPublicIP = System.Text.Encoding.UTF8.GetString(uc.Receive(ref servrIP));
        Console.WriteLine("目前電腦的IP:" + myPublicIP);
        Console.WriteLine("\n|-----------------------------------|\n");

        // 從伺服器取得對方IP:
        receive = System.Text.Encoding.UTF8.GetString(uc.Receive(ref servrIP));
        otherIP = new IPEndPoint(IPAddress.Parse(receive.Split(':')[0]), int.Parse(receive.Split(':')[1]));

        // 打洞:
        b = System.Text.Encoding.UTF8.GetBytes("Hi");
        uc.Send(b, b.Length, otherIP);

        // 為監聽{uc.Receive()}建立一條執行緒:
        // ( 1.接收/2.發送 兩種功能建議個別建立執行緒
        // 如果沒有建立執行緒程式可能會鎖死 )
        new Thread(new MyReceiveThreadClass().MyRun).Start();

        // 傳送真正的資料:
        int i = 0;
        while (true)
        {
            b = System.Text.Encoding.UTF8.GetBytes("這是 " + myPublicIP + " 資料 : " + i++);
            uc.Send(b, b.Length, otherIP);
            //Thread.Sleep(1000);
        }
    }
}

class MyReceiveThreadClass
{
    public void MyRun()
    {
        while (true)
        {
            string receive = System.Text.Encoding.UTF8.GetString(MyClient.uc.Receive(ref MyClient.otherIP));
            Console.WriteLine(receive);
        }
    }
}

 

  伺服器輸出結果:

 ccccccccccccccccc  

 

黃彥霖 發表在 痞客邦 留言(5) 人氣()