java tcp客户端:如何边读边发送数据
java tcp client: howto send data while reading
这是我使用套接字连接的第一步 java。我喜欢编写连接到服务器并读取服务器将发送的所有数据的 tcp 客户端。来自服务器的每条消息将由 0x00 终止。
第一个问题:
我如何读取这个可变消息长度?
第二个问题:
如果用户通过键盘输入文本,则该文本应在我接收时发送到服务器。但是如何在从服务器读取数据的同时发送数据呢?
到目前为止,这是我的代码:
import java.io.*;
public class Client {
public static void main(String[] args) {
Client client = new Client();
try {
client.test();
} catch (IOException e) {
e.printStackTrace();
}
}
void test() throws IOException {
String ip = "127.0.0.1"; // localhost
int port = 12345;
java.net.Socket socket = new java.net.Socket(ip,port); // verbindet sich mit Server
String zuSendendeNachricht = "Hello World0x00";
schreibeNachricht(socket, zuSendendeNachricht);
while (true){
String empfangeneNachricht = leseNachricht(socket);
System.out.println(empfangeneNachricht);
}
}
void schreibeNachricht(java.net.Socket socket, String nachricht) throws IOException {
PrintWriter printWriter =
new PrintWriter(
new OutputStreamWriter(
socket.getOutputStream()));
printWriter.print(nachricht);
printWriter.flush();
}
String leseNachricht(java.net.Socket socket) throws IOException {
BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
char[] buffer = new char[200];
int anzahlZeichen = bufferedReader.read(buffer, 0, 200); // blockiert bis Nachricht empfangen
String nachricht = new String(buffer, 0, anzahlZeichen);
System.out.println(nachricht);
}
}
以及如何读取可变消息长度
第一个问题:如何读取这个可变消息长度?
只需读取大小为 1 字节的传入数据并检查 0x00 上的每个字节。
第二个问题:如果用户通过键盘输入文本,这个文本应该发送到服务器,而我正在接收。但是如何在从服务器读取数据的同时发送数据呢?
启动两个独立的线程。一种用于阅读,一种用于写作。
伪代码:
Thread readingThread = new Thread(new Runnable() {
@Override
public void run() {
//do reading here...
}
});
readingThread.start();
Thread writingThread = new Thread(new Runnable() {
@Override
public void run() {
//do writing here...
}
});
writingThread.start();
在下面找到一个读取每个字节并检查 0x00 的工作示例。这里没有使用线程。
Client.java的内容:
package tcpserverclient;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Client {
private static final Logger LOG = Logger.getLogger(Client.class.getName());
private String getData(InputStream stream2server) {
BufferedInputStream inputStream = new BufferedInputStream(stream2server);
StringBuilder incomingData = new StringBuilder("");
try {
int c;
LOG.info("reading incoming data...");
while ((c = inputStream.read()) != -1) {
if (c == 0) {
break;
} else {
incomingData.append((char) c);
System.out.print((char) c);
}
}
LOG.info("\ndata complete.");
} catch (IOException ex) {
ex.printStackTrace();
}
return incomingData.toString();
}
private void startListen(int port) {
try {
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
LOG.info("\nListening on port " + port);
Socket socket = serverSocket.accept();
LOG.info("incoming call...");
InputStream incoming = socket.getInputStream();
OutputStream outgoing = socket.getOutputStream();
String data = getData(incoming);
LOG.info(data);
outgoing.close();
incoming.close();
socket.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
new Client().startListen(9999);
}
}
Server.java的内容:
package tcpserverclient;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Server {
public void sendCommand(String ip, int port, String cmd) {
try {
Socket socket = new Socket(ip, port);
InputStream fromServer = socket.getInputStream();
OutputStream toServer = socket.getOutputStream();
socket.setSoTimeout(0);
byte[] ba = cmd.getBytes();
byte[] ba0 = new byte[ba.length + 1];
System.arraycopy(ba, 0, ba0, 0, ba.length);
ba0[ba.length] = 0;
toServer.write(ba0);
fromServer.close();
toServer.close();
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
new Server().sendCommand("127.0.0.1", 9999, "Hal, can you read me?");
}
}
先启动 Client.java,然后启动 Server.java。输出是这样的:
run:
Jan 06, 2015 9:19:42 AM tcpserverclient.Client startListen
Information:
Listening on port 9999
Jan 06, 2015 9:19:44 AM tcpserverclient.Client startListen
Information: incoming call...
Jan 06, 2015 9:19:44 AM tcpserverclient.Client getData
Information: reading incoming data...
Jan 06, 2015 9:19:44 AM tcpserverclient.Client getData
Information:
data complete.
Jan 06, 2015 9:19:44 AM tcpserverclient.Client startListen
Information: Hal, can you read me?
Jan 06, 2015 9:19:44 AM tcpserverclient.Client startListen
Information:
Listening on port 9999
Hal, can you read me?
您能否修改服务器以使用行结尾而不是“0x00”来终止消息?如果是这样,那么您将能够使用 readLine 而不是使用 bufferedReader 进行读取,这将允许您读取可变消息。
您不需要在每次循环运行时都初始化 bufferedReader,您可以在开始时初始化它,然后在循环中调用 read/write 方法。
要边读边写,您需要有一个从 stdin 读取的 BufferedReader,然后您需要在我之前提到的 while 循环中从它读取并写入您的输出流。
此页面包含所有代码示例和解释:http://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html
这是我使用套接字连接的第一步 java。我喜欢编写连接到服务器并读取服务器将发送的所有数据的 tcp 客户端。来自服务器的每条消息将由 0x00 终止。
第一个问题: 我如何读取这个可变消息长度?
第二个问题: 如果用户通过键盘输入文本,则该文本应在我接收时发送到服务器。但是如何在从服务器读取数据的同时发送数据呢?
到目前为止,这是我的代码:
import java.io.*;
public class Client {
public static void main(String[] args) {
Client client = new Client();
try {
client.test();
} catch (IOException e) {
e.printStackTrace();
}
}
void test() throws IOException {
String ip = "127.0.0.1"; // localhost
int port = 12345;
java.net.Socket socket = new java.net.Socket(ip,port); // verbindet sich mit Server
String zuSendendeNachricht = "Hello World0x00";
schreibeNachricht(socket, zuSendendeNachricht);
while (true){
String empfangeneNachricht = leseNachricht(socket);
System.out.println(empfangeneNachricht);
}
}
void schreibeNachricht(java.net.Socket socket, String nachricht) throws IOException {
PrintWriter printWriter =
new PrintWriter(
new OutputStreamWriter(
socket.getOutputStream()));
printWriter.print(nachricht);
printWriter.flush();
}
String leseNachricht(java.net.Socket socket) throws IOException {
BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
char[] buffer = new char[200];
int anzahlZeichen = bufferedReader.read(buffer, 0, 200); // blockiert bis Nachricht empfangen
String nachricht = new String(buffer, 0, anzahlZeichen);
System.out.println(nachricht);
}
}
以及如何读取可变消息长度
第一个问题:如何读取这个可变消息长度?
只需读取大小为 1 字节的传入数据并检查 0x00 上的每个字节。
第二个问题:如果用户通过键盘输入文本,这个文本应该发送到服务器,而我正在接收。但是如何在从服务器读取数据的同时发送数据呢?
启动两个独立的线程。一种用于阅读,一种用于写作。
伪代码:
Thread readingThread = new Thread(new Runnable() {
@Override
public void run() {
//do reading here...
}
});
readingThread.start();
Thread writingThread = new Thread(new Runnable() {
@Override
public void run() {
//do writing here...
}
});
writingThread.start();
在下面找到一个读取每个字节并检查 0x00 的工作示例。这里没有使用线程。
Client.java的内容:
package tcpserverclient;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Client {
private static final Logger LOG = Logger.getLogger(Client.class.getName());
private String getData(InputStream stream2server) {
BufferedInputStream inputStream = new BufferedInputStream(stream2server);
StringBuilder incomingData = new StringBuilder("");
try {
int c;
LOG.info("reading incoming data...");
while ((c = inputStream.read()) != -1) {
if (c == 0) {
break;
} else {
incomingData.append((char) c);
System.out.print((char) c);
}
}
LOG.info("\ndata complete.");
} catch (IOException ex) {
ex.printStackTrace();
}
return incomingData.toString();
}
private void startListen(int port) {
try {
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
LOG.info("\nListening on port " + port);
Socket socket = serverSocket.accept();
LOG.info("incoming call...");
InputStream incoming = socket.getInputStream();
OutputStream outgoing = socket.getOutputStream();
String data = getData(incoming);
LOG.info(data);
outgoing.close();
incoming.close();
socket.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
new Client().startListen(9999);
}
}
Server.java的内容:
package tcpserverclient;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Server {
public void sendCommand(String ip, int port, String cmd) {
try {
Socket socket = new Socket(ip, port);
InputStream fromServer = socket.getInputStream();
OutputStream toServer = socket.getOutputStream();
socket.setSoTimeout(0);
byte[] ba = cmd.getBytes();
byte[] ba0 = new byte[ba.length + 1];
System.arraycopy(ba, 0, ba0, 0, ba.length);
ba0[ba.length] = 0;
toServer.write(ba0);
fromServer.close();
toServer.close();
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
new Server().sendCommand("127.0.0.1", 9999, "Hal, can you read me?");
}
}
先启动 Client.java,然后启动 Server.java。输出是这样的:
run:
Jan 06, 2015 9:19:42 AM tcpserverclient.Client startListen
Information:
Listening on port 9999
Jan 06, 2015 9:19:44 AM tcpserverclient.Client startListen
Information: incoming call...
Jan 06, 2015 9:19:44 AM tcpserverclient.Client getData
Information: reading incoming data...
Jan 06, 2015 9:19:44 AM tcpserverclient.Client getData
Information:
data complete.
Jan 06, 2015 9:19:44 AM tcpserverclient.Client startListen
Information: Hal, can you read me?
Jan 06, 2015 9:19:44 AM tcpserverclient.Client startListen
Information:
Listening on port 9999
Hal, can you read me?
您能否修改服务器以使用行结尾而不是“0x00”来终止消息?如果是这样,那么您将能够使用 readLine 而不是使用 bufferedReader 进行读取,这将允许您读取可变消息。
您不需要在每次循环运行时都初始化 bufferedReader,您可以在开始时初始化它,然后在循环中调用 read/write 方法。
要边读边写,您需要有一个从 stdin 读取的 BufferedReader,然后您需要在我之前提到的 while 循环中从它读取并写入您的输出流。
此页面包含所有代码示例和解释:http://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html