一、TCP/UDP对比
二、TCP编程
- TCP字节流编程
- Server端:
public class TCPServerStream {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(9999)) {
System.out.println("server start at port:9999....");
Socket accept = serverSocket.accept();
System.out.println("client has already connected");
try (InputStream inputStream = accept.getInputStream();
OutputStream outputStream = accept.getOutputStream()) {
byte[] bytes=new byte[1024];
int text;
while ((text=inputStream.read(bytes))!=-1)
{
System.out.println(new String(bytes,0,text));
}
outputStream.write("hello client".getBytes());
System.out.println("server exit...");
}
} catch (IOException e) {
e.printStackTrace();
};
}
}
public class TCPClientStream {
public static void main(String[] args) {
System.out.println("client connecting......");
try (Socket socket = new Socket(InetAddress.getLocalHost(), 9999)) {
System.out.println("client connected......");
try (OutputStream outputStream = socket.getOutputStream();
InputStream inputStream=socket.getInputStream()) {
outputStream.write(("hello server".getBytes()));
socket.shutdownOutput();
byte[] bytes=new byte[1024];
int text;
while ((text=inputStream.read(bytes))!=-1)
{
System.out.println(new String(bytes,0,text));
}
System.out.println("client exit...");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意:
- 这里调用Socket的shutdownOutput()方法,底层会告知服务端我这边已经写完了,那么服务端收到消息后,就能知道已经读取完消息,如果服务端有要返回给客户的消息那么就可以通过服务端的输出流发送给客户端,如果没有,直接关闭Socket。
- 这种方式通过关闭客户端的输出流,告知服务端已经写完了,虽然可以读到服务端发送的消息,
但是还是有一点缺点:不能再次发送消息给服务端,如果再次发送,需要重新建立Socket连接这个缺点,在访问频率比较高的情况下将是一个需要优化的地方。
优化文章
- TCP字符流编程
public class TCPServerCharacterStream extends Thread{
private ServerSocket serverSocket;
public static void main(String[] args) {
TCPServerCharacterStream tcpServerCharacterStream=new TCPServerCharacterStream();
tcpServerCharacterStream.start();
}
public TCPServerCharacterStream(){
try{
serverSocket = new ServerSocket(8888);
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public void run() {
while (true)
{
try {
System.out.println("server waiting for connecting....");
Socket accept = serverSocket.accept();
System.out.println("client has already connected....");
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream(), "UTF-8"));
BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(accept.getOutputStream(),"UTF-8"))
) {
System.out.println("using socket is: "+accept);
System.out.println("get message : "+bufferedReader.readLine());
bufferedWriter.write("hello client from server");
bufferedWriter.newLine();
System.out.println("server exit....");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class TCPClientCharacterStream extends Thread{
public static void main(String[] args) {
System.out.println("client connecting......");
try (Socket socket = new Socket(InetAddress.getLocalHost(), 8888)) {
System.out.println("client connected......");
try (BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"))
){
System.out.println("start to send message....");
System.out.println("using socket is: "+socket);
bufferedWriter.write("sending: hello server from client");
System.out.println("ending send message...");
bufferedWriter.newLine();
bufferedWriter.flush();
System.out.println(socket.isClosed());
System.out.println("get message : "+bufferedReader.readLine());
System.out.println("client exit...");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意:
try resource模式下,如果只是进行写操作,不像我这样读写切换的话,好像是会因为自动close而自动flush。比如我server端里面,因为写操作是在读操作后面的,所以try resource自动close后也能正常运行。但像我client里面,因为写操作后,try resource段还没运行完,就必须手动flush,才能提交。
|