线程中无法连接打印机:WiFi打印服务器开发及多行打印求助
Hey Jack, let's dig into why your persistent printer server isn't working as expected when printing from your ArrayList—even though single-line prints work and your IP/port checks out. I've seen similar issues with network printers, so here are the most likely fixes and code adjustments to get this sorted:
1. Fix Connection Persistence (The #1 Culprit)
Single-line prints work because you're opening/closing the socket quickly, but looping through an ArrayList might be causing connection flakiness if you're reinitializing the socket/stream on every print. Network printers hate frequent connect/disconnect cycles.
Solution: Initialize your printer connection once (outside the loop) and reuse the same socket/output stream for all prints. Only close it when your server shuts down.
2. Ensure Correct Line Endings & Printer Commands
Many network printers (especially thermal ones) require specific line endings (like \r\n instead of just \n) or a final "print trigger" command to flush the buffer. Single-line prints might accidentally work, but multi-line needs explicit handling.
3. Avoid Blocking the Listener Thread
If your server is handling print requests in the same thread as it listens for new connections, it'll freeze up during long print jobs. Use a thread pool to offload printing tasks.
Modified MyPrinter Class (Fixed for Persistent Printing)
import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.List; public class MyPrinter { private Socket printerSocket; private OutputStream outputStream; private final String printerIp; private final int printerPort; // Initialize connection once on startup public MyPrinter(String ip, int port) throws IOException { this.printerIp = ip; this.printerPort = port; reconnect(); // Establish initial connection } // Helper to reconnect if connection drops private void reconnect() throws IOException { if (printerSocket != null && !printerSocket.isClosed()) { closeResources(); } printerSocket = new Socket(printerIp, printerPort); printerSocket.setSoTimeout(0); // Disable timeout for long-lived connections outputStream = printerSocket.getOutputStream(); } // Print all lines from your ArrayList public void printProducts(List<Product> products) throws IOException { // Check if connection is still alive before printing if (printerSocket.isClosed() || !printerSocket.isConnected()) { reconnect(); } for (Product product : products) { // Use \r\n for proper line breaks (adjust based on your printer specs) String line = product.getProductInfo() + "\r\n"; outputStream.write(line.getBytes()); outputStream.flush(); // Force data to send immediately } // Send final print trigger (ESC/POS command for thermal printers; adjust for your model) outputStream.write("\x0C".getBytes()); // Form feed to eject paper outputStream.flush(); } // Clean up resources on server shutdown public void closeResources() throws IOException { if (outputStream != null) outputStream.close(); if (printerSocket != null) printerSocket.close(); } }
Modified Printer Server (Non-Blocking Listening)
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.util.ArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class PrinterServer { private final ServerSocket serverSocket; private final MyPrinter printer; private final ExecutorService threadPool; // Handle multiple print requests at once public PrinterServer(int serverPort, String printerIp, int printerPort) throws IOException { serverSocket = new ServerSocket(serverPort); printer = new MyPrinter(printerIp, printerPort); threadPool = Executors.newFixedThreadPool(3); // Adjust pool size based on needs System.out.println("Printer server running on port " + serverPort); } public void startListening() { while (true) { try { Socket clientSocket = serverSocket.accept(); // Offload print task to a separate thread so listener stays responsive threadPool.submit(() -> handlePrintRequest(clientSocket)); } catch (IOException e) { System.err.println("Error accepting client connection: " + e.getMessage()); } } } private void handlePrintRequest(Socket clientSocket) { try ( BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true) ) { // Assume client sends a "PRINT" command to trigger printing String request = in.readLine(); if ("PRINT".equalsIgnoreCase(request)) { // Fetch your product ArrayList (replace with your actual data source) ArrayList<Product> productList = getProductData(); printer.printProducts(productList); out.println("PRINT_SUCCESS"); } else { out.println("INVALID_REQUEST"); } } catch (IOException e) { System.err.println("Error handling print request: " + e.getMessage()); } finally { try { clientSocket.close(); } catch (IOException e) { // Ignore close errors } } } // Replace this with your actual method to get product data private ArrayList<Product> getProductData() { ArrayList<Product> products = new ArrayList<>(); products.add(new Product("Product 1: Wireless Headphones")); products.add(new Product("Product 2: Portable Charger")); products.add(new Product("Product 3: LED Desk Lamp")); return products; } public static void main(String[] args) throws IOException { // Replace with your printer IP/port and server port PrinterServer server = new PrinterServer(8080, "192.168.1.100", 9100); server.startListening(); } } // Your Product class example class Product { private final String productInfo; public Product(String info) { this.productInfo = info; } public String getProductInfo() { return productInfo; } }
Quick Troubleshooting Steps
- Test with Telnet: Run
telnet [printer-ip] 9100, type multiple lines (ending with\r\n), then send\x0C—if this prints, your printer supports the commands above. - Check Network Traffic: Use Wireshark to capture traffic to your printer's IP/port. Verify that all lines are being sent correctly.
- Printer Settings: Ensure your printer isn't set to "hold jobs" or has any network timeout settings enabled.
内容的提问来源于stack exchange,提问作者Jack Moe

