1.1、TCP,同步版本的Server:
package com.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* TCP的網絡編程,服務器
* @author Feng
*
*/
public class TCPTestServer{
public static void main(String[] args) throws IOException, InterruptedException{
//服務器開始監聽6666號端口
//從啓動上說,必須要先啓動服務器端程序
ServerSocket ss = new ServerSocket(6666);
//因爲服務器需要不斷等待連接,所以死循環等待
while(true){
System.out.println("等待連接申請中···");
//接受鏈接申請,這樣寫只接受一個連接,這個方法是阻塞式的,如果沒有任何連接申請就會一直等待
Socket s = ss.accept();
if(s.isConnected()){
System.out.println("OK!!!!!");
//使用輸入流接受客戶端傳入的信息
InputStream stream = s.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
//注意,像這種輸入流的方式屬於同步輸入,連接成功後如果客戶端不傳送東西,這裏的輸入流會一直等待,導致其他連接申請被擱置
System.out.println(reader.readLine());
}else{
System.out.println("NO!!");
}
}
}
}
1.2、TCP,同步版本的Client:
package com.socket;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* TCP網絡編程,客戶端
* @author Feng
*
*/
public class TCPTestClient {
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException{
//客戶端申請連接到 127.0.0.1:6666
//客戶端會給這邊的socket隨機分配端口號,具體是多少並不重要
Socket s = new Socket("127.0.0.1", 6666);
//連接成功之後,可以通過管道來進行通話,使用輸出管道
//這裏的等待模擬:線連接,但是遲遲不發送信息,這個時候這個鏈接會被該客戶端獨佔
Thread.sleep(10000);
OutputStream stream = s.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stream));
writer.write("SHTI!!!!你妹!!!!!");
writer.flush();
writer.close();
s.close();
}
}
2、TCP,多線程的圖片接收服務器
package com.socket;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPJpgGetter {
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket(6666);
while(true){
Socket s = ss.accept();
new Thread(new Getter(s)).start();
}
}
}
/**
* 多線程的圖片接收類
* 服務器端開啓多個線程用於接收傳送過來的圖片
*/
class Getter implements Runnable{
private Socket s = null;
public Getter(Socket s){
this.s = s;
}
@Override
public void run() {
try {
String info = s.getInetAddress().toString();
//從socket讀取數據的輸入流
InputStream getter = s.getInputStream();
//回傳數據的輸出流
OutputStream sender = s.getOutputStream();
//爲了避免文件名重複的覆蓋,使用編號
int count = 1;
File temp = new File("D:/" + info + "(" + count + ").jpg");
while(temp.exists()){
//這裏的處理不是很嚴謹,還是有可能會導致文件覆蓋
temp = new File("D:/" + info + "(" + (++count) + ").jpg");
}
System.out.println("接收到來自:" + info + "的傳送請求,存儲名爲:" + temp.getName());
//創建文件並寫入到磁盤的輸出流
FileOutputStream fileWriter = new FileOutputStream(temp);
byte[] buf = new byte[1024];
int len;
while((len=getter.read(buf)) != -1){
//寫文件的時候要注意寫的長度
fileWriter.write(buf, 0, len);
}
sender.write("上傳成功".getBytes("UTF-8"));
fileWriter.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.1、UDP,同步版本的“Server”:
package com.socket;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* UDP的“服務器”,事實上UDP並沒有明確地服務器和客戶端的分類,因爲是不安全連接,要做的就是確定目標IP和端口號,然後直接發送就好了
* @author Feng
*
*/
public class UDPTestServer {
public static void main(String[] args) throws IOException{
byte buf[] = new byte[1024];
//DatagramPacket用來存放需要發送或者要接收的數據
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//DatagramSocket就是UDP方式的socket,爲服務器指定端口號6666
DatagramSocket ds = new DatagramSocket(6666);
while(true){
//receive方法是阻塞式方法,等待接收數據
ds.receive(dp);
//獲取發送源的IP地址和端口號,在發送端由於沒有指定端口號,這裏看到的端口是系統隨機分配的端口
System.out.println("收取到來自 " + dp.getAddress() + ":" + dp.getPort() + " 的信息:");
//以字符串的形式獲取數據並打印
System.out.println("字符串:" + new String(buf, 0, dp.getLength()));
//接受傳送過來的信息,信息已經存儲在buf之中
ByteArrayInputStream in = new ByteArrayInputStream(buf);
DataInputStream din = new DataInputStream(in);
System.out.println("數字:" + din.readLong());
System.out.println();
}
}
}
3.2、UDP,同步版本的“Client”:
package com.socket;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class UDPTestClient {
public static void main(String[] args) throws IOException{
byte[] buf = new String("你好!~~").getBytes();
//將一個long類型數據轉換成byte[];
long num = 123412341234L;
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(out);
dout.writeLong(num);
byte[] buf2 = out.toByteArray();
System.out.println(buf2.length);
//新建socket的時候如果不指定端口號,那系統將爲其默認指定一個地址,作爲發送方,這個socket不需要指定端口
DatagramSocket ds = new DatagramSocket();
DatagramPacket dp = null;
//DatagramPacket是UDP模式下傳輸信息的媒介
//指定目的地址爲127.0.0.1:6666
dp = new DatagramPacket(buf, buf.length,
new InetSocketAddress("127.0.0.1", 6666));
ds.send(dp);
dp = new DatagramPacket(buf2, buf2.length,
new InetSocketAddress("127.0.0.1", 6666));
ds.send(dp);
ds.close();
}
}
4、UDP聊天小程序
package com.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
/**
* 兩個線程,定義一個接受和一個發送端
* 寫入目標機器的IP地址和端口號即可通信
* 中文問題:我的MyEclipse默認編碼是UTF-8,運行的時候要在Run-Run Configuration-Common-指定GBK,否則會出現中文亂碼問題
* @author Feng
*/
public class UDPTalker {
public static void main(String[] args) throws IOException{
InetAddress myAdd = InetAddress.getLocalHost();
System.out.println("本機地址:" + myAdd);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("請輸入目標機器IP地址:");
String ipAdd = reader.readLine();
System.out.println("請輸入目標機器端口號:");
int port = Integer.parseInt(reader.readLine());
DatagramSocket sender = new DatagramSocket();
DatagramSocket listener = new DatagramSocket(6666);
//消息發送目的地
InetSocketAddress address = new InetSocketAddress(ipAdd, port);
new Thread(new Send(sender, address)).start();
new Thread(new Listen(listener)).start();
}
}
/**
* 發送線程,接受鍵盤輸入,並將消息發往指定的地址
* @author Feng
*
*/
class Send implements Runnable{
private DatagramSocket ds = null;
private InetSocketAddress address = null;
public Send(DatagramSocket ds, InetSocketAddress address){
this.ds = ds;
this.address = address;
}
@Override
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String line = null;
try {
while((line=reader.readLine()) != null){
byte[] temp = line.getBytes("UTF-8");
//發送數據包,指定了發送的內容以及目的地
DatagramPacket dp = new DatagramPacket(temp, temp.length, address);
ds.send(dp);
if("exit".equals(line)){
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 接收線程,等待接收消息並顯示
* @author Feng
*
*/
class Listen implements Runnable{
private DatagramSocket ds = null;
public Listen(DatagramSocket ds){
this.ds = ds;
}
@Override
public void run() {
try {
while(true){
byte[] temp = new byte[1024];
//接收數據包,緩存大小爲1K
DatagramPacket dp = new DatagramPacket(temp, temp.length);
ds.receive(dp);
String address = dp.getAddress().getHostAddress() + "-" + dp.getPort();
String data = new String(dp.getData(), 0, dp.getLength(), "UTF-8");
System.out.println(address + ": " + data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}