在Java中實(shí)現(xiàn)TCP協(xié)議編程
創(chuàng)新互聯(lián)建站服務(wù)項(xiàng)目包括焦作網(wǎng)站建設(shè)、焦作網(wǎng)站制作、焦作網(wǎng)頁制作以及焦作網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,焦作網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到焦作省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
ServerSocket:編寫TCP網(wǎng)絡(luò)服務(wù)程序,首先要用到j(luò)ava.net.ServerSocket類用以創(chuàng)建服務(wù)器Socket
構(gòu)造方法:
ServerSocket(int?port):創(chuàng)建綁定到特定端口的服務(wù)器套接字
ServerSocket(int?port,?int?backlog):利用指定的backlog(服務(wù)器忙時(shí)保持連接請求的等待客戶數(shù)量),創(chuàng)建服務(wù)器套接字并將其綁定到指定的本地端口號(hào)。
ServerSocket(int?port,?int?backlog,?InetAddress?bindAddr):使用指定的端口、偵聽?backlog?和要綁定到的本地?IP?地址創(chuàng)建服務(wù)器。
Socket:客戶端要與服務(wù)器建立連接,必須先創(chuàng)建一個(gè)Socket對象
常用構(gòu)造方法
Socket(String?host,?int?port):創(chuàng)建一個(gè)流套接字并將其連接到指定主機(jī)上的指定端口號(hào)。
Socket(InetAddress?address,?int?port):創(chuàng)建一個(gè)流套接字并將其連接到指定?IP?地址的指定端口號(hào)。
服務(wù)器端程序調(diào)用ServerSocket類中的accept()方法等待客戶端的連接請求,一旦accept()接收了客戶端連接請求,該方法返回一個(gè)與該客戶端建立了專線連接的Socket對象,不用程序去創(chuàng)建這個(gè)Socket對象。建立了連接的兩個(gè)Socket是以IO流的方式進(jìn)行數(shù)據(jù)交換的,Java提供了Socket類中的getInputStream()返回Socket的輸入流對象,getOutputStream()返回Socket的輸出流對象。
TCP服務(wù)器與TCP客戶端間的數(shù)據(jù)的接受圖示:
創(chuàng)建一個(gè)TCP服務(wù)器端程序的步驟
(1)創(chuàng)建一個(gè)ServerSocket
(2)從ServerSocket接受客戶連接請求
(3)創(chuàng)建一個(gè)服務(wù)線程處理新的連接
(4)在服務(wù)線程中,從socket中獲得I/O流
(5)對I/O流進(jìn)行讀寫操作,完成與客戶的交互
(6)關(guān)閉I/O流
(7)關(guān)閉Socket
ServerSocket?server=new?ServerSocket(port)
Socket?s?=server.accept();
ObjectInputStream?in=new?ObjectInputStream(s.getInputStream());
ObjectOutputStream?out=new?ObjectOutputStream(s.getOutputStream());
out.close();
in.close();
s.close();
創(chuàng)建一個(gè)TCP客戶端程序的步驟
(1)創(chuàng)建Socket
(2)獲得I/O流
(3)對I/O流進(jìn)行讀寫操作
(4)關(guān)閉I/O流
(5)關(guān)閉Socket
Socket?connection?=new?Socket(127.0.0.1,9009);
ObjectInputStream?input=new?ObjectInputStream(connection.getInputStream());
ObjectOutputStream?output=new?ObjectOutputStream(connection.getOutputStream());
output.close();
input.close();
connection.close();
用TCP實(shí)現(xiàn)服務(wù)器與客戶端的“聊天”:
實(shí)例代碼:
客戶端:
package?com.hbsi.net;
import?java.net.Socket;
import?java.io.*;
public?class?TcpClient{
public?static?void?main(String[]?args)?throws?Exception?{
//?1.建立tcp客戶端socket,要確定要連接的服務(wù)器ip,port
Socket?s?=?new?Socket("192.168.49.87",?9009);
//?獲取鍵盤錄入
BufferedReader?br?=?new?BufferedReader(new?InputStreamReader(System.in));
//?2.通過建立的socket,獲取輸出流對象
//?數(shù)據(jù)輸出給服務(wù)器端
OutputStream?out?=?s.getOutputStream();
BufferedWriter?bwout?=?new?BufferedWriter(new?OutputStreamWriter(out));
//?獲取服務(wù)器端返回的數(shù)據(jù)
//?讀取服務(wù)器端發(fā)過來的信息InputStreamReader()
BufferedReader?brin?=?new?BufferedReader(new?InputStreamReader(
s.getInputStream()));
String?line?=?null;
while?((line?=?br.readLine())?!=?null)?{
if?(line.equals("over"))
break;
bwout.write(line);
bwout.newLine();
bwout.flush();
String?str?=?brin.readLine();
System.out.println("server:"?+?str);
}
br.close();
s.close();
}
}
服務(wù)器端:
package?com.hbsi.net;
import?java.io.BufferedReader;
import?java.io.BufferedWriter;
import?java.io.InputStream;
import?java.io.InputStreamReader;
import?java.io.OutputStreamWriter;
import?java.net.ServerSocket;
import?java.net.Socket;
public?class?TcpServer{
public?static?void?main(String[]?args)?throws?Exception?{
//?1.建立服務(wù)器socket
ServerSocket?ss?=?new?ServerSocket(9009);
//?2.調(diào)用accept()
Socket?s?=?ss.accept();
System.out.println(s.getInetAddress().getHostAddress()
+?"...connection");
//?讀取客戶的信息的輸入流
InputStream?in?=?s.getInputStream();
BufferedReader?brin?=?new?BufferedReader(new?InputStreamReader(in));
//?向客戶端發(fā)送信息輸出流,服務(wù)端向客戶端返回信息OutputStreamWriter()
BufferedWriter?brout?=?new?BufferedWriter(new?OutputStreamWriter(
s.getOutputStream())); String?line?=?null;
while?((line?=?brin.readLine())?!=?null)?{
System.out.println("client:"?+?line);
brout.write(line.toUpperCase());//服務(wù)器端收到信息后,將信息轉(zhuǎn)為大寫返回給客戶端toUpperCase()
brout.newLine();
brout.flush();
}
s.close();
ss.close();
}
}
localhost是指你本機(jī),它可以改成127.0.0.1,如果跟其他機(jī)器通訊就改成另一臺(tái)機(jī)器的ip地址。8800是指通訊端口;
你把OS里的O理解為output,IS里的I理解為input。OS是輸出端,輸出端把數(shù)據(jù)放到BufferedReader,BufferedReader通過端口傳輸?shù)絀S后,再讀取。
服務(wù)器監(jiān)聽端口 做個(gè)無限循環(huán) 接到一個(gè)連接就創(chuàng)建一個(gè)通道線程,并將通道線程存儲(chǔ)到一個(gè)list集合中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/*
* 4.用socket通訊寫出多個(gè)客戶端和一個(gè)服務(wù)器端的通訊,
* 要求客戶發(fā)送數(shù)據(jù)后能夠回顯相同的數(shù)據(jù)(回顯功能)(實(shí)用TCP方式)。
*/
public class Test4Server {
// 主入口
public static void main(String[] args) throws IOException {
scoketServer();
}
// 開啟的tcp8888監(jiān)聽端口
public static void scoketServer() throws IOException {
ServerSocket server = new ServerSocket(8888);
while (true) {
// 未連通前線程阻塞,連通后開啟一個(gè)socket通道線程后繼續(xù)監(jiān)聽8888端口
Socket socket = server.accept();
System.out.println(socket.getInetAddress().getHostAddress()
+ "連接進(jìn)入");
new SocketThread(socket).start();
}
}
}
// 一個(gè)服務(wù)器端口中監(jiān)聽多個(gè)客服端通道線程
class SocketThread extends Thread {
// 所有通道寫入流的集合
private static ListPrintWriter list =new ArrayListPrintWriter();
private BufferedReader bufferedReader;
private PrintWriter printWriter;
public SocketThread(Socket socket) throws IOException {
this.bufferedReader = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
this.printWriter = new PrintWriter(socket.getOutputStream());
list.add(printWriter);
}
@Override
public void run() {
String string = null;
while (true) {
try {
// 服務(wù)器在通道中讀到的信息回顯給客服端
string = bufferedReader.readLine();
System.out.println("客服端信息:" + string);
for(PrintWriter printWriter:list ){
printWriter.write("服務(wù)器回顯:" + string + "\r\n");
printWriter.flush();
}
} catch (IOException e) {
}
}
}
}
客服端代碼 可以用在局域網(wǎng)中用多臺(tái)來連接測試
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Test4Client {
public static Object obj = new Object();
// 客服端的主入口
public static void main(String[] args) throws IOException {
socketClient();
}
// 與服務(wù)器連通地址本機(jī)(127.0.0.1),局域網(wǎng)中其他機(jī)器是(服務(wù)器在局域網(wǎng)中的ip地址) 端口都是8888
public static void socketClient() throws IOException {
Socket socket = new Socket("127.0.0.1", 8888);
if (socket.isConnected()) {
// 如果連接成功了就開啟寫和讀的進(jìn)程
new writer(socket).start();
new read(socket).start();
} else {
System.out.println("服務(wù)器未開啟");
}
}
}
// 寫入到通道的線程
class writer extends Thread {
@SuppressWarnings("unused")
private Socket socket;
private PrintWriter printWriter;
private Scanner scanner = new Scanner(System.in);
private String str = null;
public writer(Socket socket) throws IOException {
this.socket = socket;
this.printWriter = new PrintWriter(socket.getOutputStream());
}
@Override
public void run() {
scanner.useDelimiter("\r\n");
while (true) {
System.out.print("請輸入信息:");
// 產(chǎn)生掃描器的線程阻塞
str = scanner.next();
System.out.println("我說:"+str);
printWriter.write(str + "\r\n");
printWriter.flush();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 從通道中讀取的線程
class read extends Thread {
private Socket socket;
private BufferedReader bufferedReader;
private String str = null;
public read(Socket socket) throws IOException {
this.socket = socket;
this.bufferedReader = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
}
@Override
public void run() {
while (true) {
try {
str = bufferedReader.readLine();
System.out.println(str);
} catch (IOException e) {
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}