1、什么是Socket?
Socket是连接运行在网络上的两个程序间的双向通讯的端点。
2、使用Socket进行网络通信的过程
(1)服务器程序将一个套接字绑定到一个特定的端口,并通过此套接字等待和和监听客户的连接请求。
(2)客户程序根据服务器程序所在的主机名和端口号发出连接请求。
(3)如果一切正常,服务器接受连接请求。并获得一个新的绑定到不同端口地址的套接字。
(4)客户和服务器通过读写套接字进行通讯。
(5)使用ServerSocket和Socket实现服务器端和客户端的Socket通信总结:
- 建立Socket连接
- 获得输入/输出流
- 读/写数据
- 关闭输入/输出流
- 关闭Socket
3、代码实现
(1)未使用线程的实现
- 服务器端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 使用ServerSocket和Socket实现服务器端和客户端的 Socket通信
* 这是服务器端
* @author Chuan
*
*/
public class TcpServer
{
public static void main(String[] args) throws IOException
{
ServerSocket serverSocket = new ServerSocket(5000);
Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
//读取客户端的会话
byte[] buffer = new byte[1024];
int length = is.read(buffer);
System.out.println(new String(buffer, 0, length));
os.write("welcom".getBytes());
is.close();
os.close();
socket.close();
serverSocket.close();
}
}
- 客户端代码
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 使用ServerSocket和Socket实现服务器端和客户端的 Socket通信
* 这是客户端
* @author Chuan
*
*/
public class TcpClient
{
public static void main(String[] args) throws UnknownHostException, IOException
{
Socket socket = new Socket("127.0.0.1", 5000);
OutputStream oStream = socket.getOutputStream();
InputStream iStream = socket.getInputStream();
//向服务端发送消息
oStream.write("hello".getBytes());
//读取服务端发送过来的消息
byte[] buffer = new byte[1024];
int length = iStream.read(buffer);
System.out.println(new String(buffer, 0, length));
oStream.close();
iStream.close();
socket.close();
}
}
(2)使用线程实现
- 服务器端MainServer
服务器端使用了两个线程:接收会话线程ServerInputThread,发送会话线程ServerOutputThread。需要注意的是在服务端使用了一个whlie循环,而客户端没有。这样做的原因是服务端可能需要处理来自不同客户端的连接将请求,没有一个客户端请求连接就会获得一个新的绑定到不同端口地址的套接字。
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
*服务器端
* @author Chuan
*
*/
public class MainServer
{
public static void main(String[] args) throws IOException
{
@SuppressWarnings("resource")
ServerSocket ss = new ServerSocket(4000);
/**
* 此处的while循环是为了可能有多个客户端,但是本程序中当有多个客户端时,
* 客户端向服务端发消息没问题,服务端再往客户端发消息就会出问题,不能发送给相应的客户端
*/
while (true)
{
Socket socket = ss.accept();
new ServerInputThread(socket).start();
new ServerOutputThread(socket).start();
}
}
}
- 接收会话线程ServerInputThread
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
/*
* 服务器端的读取会话线程
*/
public class ServerInputThread extends Thread
{
private Socket socket;
public ServerInputThread(Socket socket)
{
this.socket = socket;
}
@Override
public void run()
{
try
{
InputStream is = socket.getInputStream();
byte[] buffer = new byte[1024];
int length;
while (true)
{
length = is.read(buffer);
System.out.println(new String(buffer, 0, length));
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- 发送会话线程ServerOutputThread
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
/*
* 服务器端的发送会话线程
*/
public class ServerOutputThread extends Thread
{
private Socket socket;
public ServerOutputThread(Socket socket)
{
this.socket = socket;
}
@Override
public void run()
{
try
{
OutputStream os = socket.getOutputStream();
while (true)
{
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
String str = br.readLine();
os.write(str.getBytes());
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- 客户端代码MainClient
客户端代码中也使用了两个线程:接收会话线程ClientInputThread,发送会话线程ClientOutputThread
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 客户端
* @author Chuan
*
*/
public class MainClient
{
public static void main(String[] args) throws UnknownHostException, IOException
{
Socket socket = new Socket("127.0.0.1", 4000);
new ClientInputThread(socket).start();
new ClientOutputThread(socket).start();
}
}
- 接收会话线程ClientInputThread,和服务端接手会话线程大同小异
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
/**
* 客户端的读取会话线程
*/
public class ClientInputThread extends Thread
{
private Socket socket;
public ClientInputThread(Socket socket)
{
this.socket = socket;
}
@Override
public void run()
{
try
{
InputStream is = socket.getInputStream();
byte[] buffer = new byte[1024];
int length;
while (true)
{
length = is.read(buffer);
System.out.println(new String(buffer, 0, length));
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- 发送会话线程ClientOutputThread
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
/**
* 客户端的发送会话线程
*/
public class ClientOutputThread extends Thread
{
private Socket socket;
public ClientOutputThread(Socket socket)
{
this.socket = socket;
}
@Override
public void run()
{
try
{
OutputStream os = socket.getOutputStream();
while (true)
{
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
String str = br.readLine();
os.write(str.getBytes());
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}