java-socket编程

socket

TCP

单线程

示例一

简单的一个实例,服务器收到客户端发送的问候。结束。

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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import org.junit.Test;

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

/**
* @author lh
* create 2019-12-13-19:30
*/
public class TCPtest1 {
//客户端
@Test
public void client() {
Socket socket = null;
OutputStream os = null;
try {
socket = new Socket("localhost", 8888);
os = socket.getOutputStream();
os.write("你好,我是客户端".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}

}
}

}

@Test
public void server() {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
//1.创建服务器端的ServerSocket,指明自己的端口号
serverSocket = new ServerSocket(8888);
//2.掉用accept()表示接收来自客户端的socke
socket = serverSocket.accept();
//3.获取输入流
is = socket.getInputStream();

byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[5];
int len;
while ((len = is.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
System.out.println(byteArrayOutputStream.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if (byteArrayOutputStream != null) {
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}

}
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}


}


}

示例二

服务器收到后,给客户端反馈信息。结束

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
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
import org.junit.Test;

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

/**
* @author lh
* create 2019-12-13-20:20
*
* 这里就不做try catch了 实际是要的
*/
public class TCPtest2 {
@Test
public void client() throws IOException {
//1.
Socket socket = new Socket("127.0.0.1",8889);
//2.
OutputStream os = socket.getOutputStream();
//3.
FileInputStream fis = new FileInputStream(new File("1.jpg"));
//4.
byte[] buffer = new byte[1024];
int len ;
while ((len = fis.read(buffer))!= -1) {
os.write(buffer,0,len);
}
socket.shutdownOutput();
//5.接收来自于服务器的信息
InputStream inputStream = socket.getInputStream();
ByteOutputStream byteOutputStream = new ByteOutputStream();
byte[] buf= new byte[20];
int lenth;
while ((lenth = inputStream.read(buf)) != -1) {
byteOutputStream.write(buf,0,lenth);
}
System.out.println(byteOutputStream.toString());
//6.
fis.close();
os.close();
socket.close();
}

@Test
public void server() throws IOException {
//1.
ServerSocket ss = new ServerSocket(8889);
//2.
Socket socket = ss.accept();
//3.
InputStream is = socket.getInputStream();
//4.
FileOutputStream fileOutputStream = new FileOutputStream(new File("socket.jpg"));
//5.
byte[] buffer = new byte[1024];
int len ;
while ((len = is.read(buffer)) != -1) {
fileOutputStream.write(buffer,0,len);
}
System.out.println("shoudao");
//6.服务器给客户端反馈
OutputStream outputStream = socket.getOutputStream();
outputStream.write("服务器已经收到了".getBytes());
//7.
fileOutputStream.close();
is.close();
socket.close();
ss.close();
}
}

示例三(简单聊天)

TCP 实现客户端和服务器简单聊天

使用TCP实现简单的聊天功能

客户端部分代码

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
import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
* TCP 实现客户端和服务器简单聊天
* 客户端
*/
public class Client {
public static void main(String[] args) throws IOException {
// 指定服务器的IP地址 端口号
Socket socket=new Socket("localhost",7832);
System.out.println("***********客户端界面*************");
System.out.println("与服务器连接成功!");
InputStream is=socket.getInputStream();//得到Socket自带的输入流
OutputStream os=socket.getOutputStream();//得到Socket自带的输出流

BufferedReader br=new BufferedReader(new InputStreamReader(is));//将输入流 放入 缓存中
PrintWriter pw=new PrintWriter(os,true);//通过输出流向服务器发消息

Scanner input=new Scanner(System.in);
String str=null;

do{
str=input.nextLine();
pw.println(str);//发消息
System.out.println("服务器:"+br.readLine());//收消息
}while (!str.equalsIgnoreCase("bye"));
}
}

服务器部分代码

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
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
* TCP 实现客户端和服务器简单聊天
* 服务器
*/
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server=new ServerSocket(7832);//Socket的服务器 并且指定端口号
Socket socket=server.accept();//侦听连接请求,等待连接
System.out.println("************服务器端界面************");
System.out.println("与客户端连接成功!");
InputStream ins=socket.getInputStream();//返回此套接字的输入流。
OutputStream ous=socket.getOutputStream();//返回此套接字的输出流。

BufferedReader br=new BufferedReader(new InputStreamReader(ins));//将客户端那边的信息 放入缓存流
PrintWriter pw=new PrintWriter(ous,true);//通过Socket自带的流将数据输出到客户端

Scanner input=new Scanner(System.in);
String str=null;
do{ //让客户端和服务器一直发送消息
System.out.println("客户端:"+br.readLine());//显示客户端的信息
str=input.nextLine();
pw.println(str); //将信息输出到客户端
}while (!str.equalsIgnoreCase("bye"));
}
}

TCP聊天室

https://blog.csdn.net/sinat_42483341/article/details/97987329

多线程

客户端代码

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
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;


/**
*
* 客户端
* 建两个类读、写
*/
public class Client1{

public static void main(String[] args) {
try {

Socket client = new Socket("127.0.0.1", 8888);
System.out.println("***********客户端界面*************");
System.out.println("与服务器连接成功!");
new ClientRead(client).start();
new ClientWrite(client).start();
}catch (IOException e){
e.printStackTrace();
}
}
}

//读服务器信息
class ClientRead extends Thread {
private Socket client;

public ClientRead(Socket client) {
this.client = client;
}

@Override
public void run() {
super.run();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line = "";
while (true) {
line = br.readLine();
if (!line.isEmpty()) {
System.out.println("服务器说:" + line);
}
if (line.equals("bye")) { //读到bye结束
System.out.println("聊天结束!");
return;
}
}
} catch (IOException e) {
e.printStackTrace();
}

}

}
//写到服务器信息,回应
class ClientWrite extends Thread {
private Socket client;

public ClientWrite(Socket client) {
this.client = client;
}

@Override
public void run() {
super.run();
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
String str = "";
while (true) {
str = input.readLine();
bw.write(str);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

服务器代码

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
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;


/**
*
* 服务器
* 建两个类,读写
*/
public class Server1 {

public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(8888);
System.out.println("************服务器端界面************");
Socket accept = ss.accept();
System.out.println("与客户端连接成功!");
new ServerRead(accept).start();
new ServerWrite(accept).start();
} catch (IOException e) {
e.printStackTrace();
}

}
}
//读客户端信息线程
class ServerRead extends Thread {
private Socket s;

public ServerRead(Socket s) {
this.s = s;
}

@Override
public void run() {
super.run();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = "";
while (true) {
line = br.readLine();
if (!line.isEmpty()) {
System.out.println("客户端说:" + line);
}
if (line.equals("bye")) { //读到bye结束
System.out.println("聊天结束!");
return;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//回应客户端信息线程,写
class ServerWrite extends Thread {
private Socket socket;

public ServerWrite(Socket socket) {
this.socket = socket;
}

@Override
public void run() {
super.run();
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String str = "";
while (true) {
str = input.readLine();
bw.write(str);
bw.newLine();
bw.flush();
}

} catch (IOException e) {
e.printStackTrace();
}
}
}

img

img

UDP

示例一

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
import org.junit.Test;

import javax.sql.DataSource;
import java.io.IOException;
import java.net.*;

/**
* @author lh
* create 2019-12-15-14:56
*/
public class UDPtest {
@Test
public void sender() throws IOException {
DatagramSocket datagramSocket = new DatagramSocket();
String str = "我是UDP发送";
byte[] data = str.getBytes();
InetAddress inetAddress = InetAddress.getLocalHost();

DatagramPacket datagramPacket = new DatagramPacket(data, data.length, inetAddress, 9090);
datagramSocket.send(datagramPacket);
datagramSocket.close();
}

@Test
public void receiver() throws IOException {
DatagramSocket socket = new DatagramSocket(9090);
byte[] buffer = new byte[100];
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
socket.receive(packet);
System.out.println(new String(packet.getData(),0,packet.getLength()));
}
}

示例二

基于UDP的socket编程 单向聊天 与 双向聊天

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.lang.*;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

/**
* @author lh
* create 2019-12-15-15:43
* UDP 实现客户端和服务器简单聊天
*/
public class UDPClient {
static DatagramSocket socket;
private int port = 8080;
static DatagramPacket packet;

public static void main(String[] args) throws IOException {
new UDPClient().service();
}

private void service() throws IOException {
socket = new DatagramSocket();
System.out.println("************客户端端界面************");
int flag;
while (true) {
flag =send();
if (flag == -1){
System.out.println("程序结束");
return;
}
receive();
}
}

private int send() throws IOException{
Scanner input = new Scanner(System.in);
String context = input.nextLine();
byte[] bytes = context.getBytes();
try {
socket.connect(InetAddress.getByName("localhost"), port);
} catch (UnknownHostException e) {
e.printStackTrace();
}
packet = new DatagramPacket(bytes, bytes.length);
try {
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("client:" + context);
if (context.equals("bye")) {
return -1;
}else return 0;
}

private void receive() {
byte[] b = new byte[100];
packet = new DatagramPacket(b, 0, b.length);
try {
socket.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
byte[] data = packet.getData();
System.out.println("server:" + new String(data));
if (new String(data).equals("bye")) {
System.out.println("程序结束");
return;
}
}



}

心得体会

  1. 基于Socket的TCP编程:

客户端Socket的工作过程包含以下三个步骤:

(1)创建 Socket :根据指定服务端的 IP 地址或端口号构造 Socket 类对象

(2)打开连接到 Socket 的输入/出流;按照一定的协议对 Socket 进行读/写操作:使用 getInputStream()方法获得输入流,使用 getOutputStream()方法获得输出流,进行数据传输

(3)关闭Socket

服务器程序的工作过程包含以下四个基本的步骤:

(1)调用 ServerSocket(int port) :创建一个服务器端套接字,并绑定到指定端口 上。用于监听客户端的请求

(2)调用 accept():监听连接请求

(3)调用 该Socket类对象的 getOutputStream() 和 getInputStream ():获取输出流和输入流

(4)关闭ServerSocket和Socket对象

2.编程中用到了IO 流的一些知识。socket编程中用Socket类对象的 getOutputStream() 和 getInputStream ()获取输出流和输入流,之后要用别的流来包装它。在读取字符时,使用字节流比较好,因此可以先用转换流inputstreamread包装getInputStream (),然后再用缓冲流包装。OutputStream功能并不强大,但是可以和java.io.PrintStream类配合使用,使之能够输出一行。

3.UDP是不可靠的,如果你先运行UDP客户端,它是不会有异常的,它只管发;而使用TCP的时候,它是会去握手的,如果没有连接上会抛出异常。

4.写代码的时候要记得写好程序结束的代码。单线程可以用retrun返回特殊值来标识结束。

参考:

https://blog.csdn.net/Chianz632/article/details/80018531

https://blog.csdn.net/qq_40791843/article/details/90675746

https://blog.csdn.net/sinat_42483341/article/details/97987329