相信直接编写简单的Socket客户端和Socketserver服务端很多人都会写,并且发现代码没什么错误,只是自己不知道运行出错原因在哪里。这里我就总的把我遇到的问题说一下,大神请过,像我一样的渣渣可以借鉴。
我是打算编写一个简单的程序实现客户端输入字符串服务器实现逆转后返回到客户端输出。首先看下图CS之间的交互原理。两边都需要都输入输出双向监听,并且相对应的,简单的说就是客户端输出,那么服务端就要输入。。。
但总是会出现如“Socket: Connection refused: connect”还有Software caused connection abort: recv failed等情况,因为问题出现的原因很多我这里就分析我出现的原因。
1.“Socket: Connection refused: connect”:原因就是你的服务端还没有启动你就启动客户端,或者是你修改过服务端端口号你没有再次启动服务端就直接就启动客户端来连接了,再者由于两边的端口号不一致这些原因都会导致。
2.Software caused connection abort: recv failed:使用8080端口时,一般不建议使用80还有一些特殊端口,
3.还有对于度娘有的说的通过inputstream的available()方法来判断,是否有响应结果.
如果available()的返回值为0,说明没有响应数据,可能是对方已经断开连接,
如果available()的返回值大于0,说明有响应数据.如果在我没有测试错误的情况下这里我个人测试并不是这样,而是相反的。
4.Address already in use: JVM_Bind如果端口号已经被使用时就会出现这种情况,如果连续很多端口都这样说明修改使用过的端口太多,dos下面运行netstat -anol来关闭掉一些进程端口就ok。或者重新启动服务端再来启动客户端。
4.看下面代码分析吧
服务端代码:
package page5;客户端代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class Server {
public static void main(String[] args) throws UnknownHostException {
Socket socket = null;
ServerSocket serverSocket=null;
try {
while(true){
serverSocket= new ServerSocket(8081);//创建绑定端口8000的对象ServerSocket
System.out.println("服务器已经启动");
socket = serverSocket.accept();//接收客户端请求,得到Socket
System.out.println("有客户端连接过来了");
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));//创建带缓冲的字符读入流
String sr = br.readLine();//读取一个文本行
PrintStream ps = new PrintStream(socket.getOutputStream());//此输出流不会抛出异常
ps.println(new StringBuffer(sr).reverse());//将反转后的字符串打印到客户端屏幕上
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(socket != null)
socket.close();
if(serverSocket != null)
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package page5;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args){
Socket socket = null;
try {
socket = new Socket("localhost",8081);//创建Socket, 请求服务端
System.out.println("客户端已经连接上");
while(true){
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
Scanner scanner = new Scanner(System.in); // 创建Scanner
System.out.println("请输入一个字符串6:"); // 给出提示输入
String line = scanner.nextLine(); // 从键盘输入读取一行
ps.println(line);//发送到服务端
ps.flush();
if((socket.getInputStream().available())==0)
System.out.println(br.readLine());// 读取服务端发回的字符串, 打印
}
} catch (Exception e){
e.printStackTrace();
}finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
1.启动服务端控制台输出
可以发现运行到socket = serverSocket.accept();这里是就开始阻塞,并没有运行输出下一句 System.out.println("有客户端连接过来了");
而我们启动客户端控制台输出
这是我们点击下图这里来查看之前的服务端程序
发现如下图这时候说明客户端服务端已经连接上了
再返回客户端输入字符串,让服务端把字符串变为逆转后返回,我们再点击上图位置查看客户端发现下图,成功转化。
同样我们可以测试上面说的available()返回值问题改为大于0时没有输出,API文档里说,这个方法不保证返回数据的准确性,最后用Common-IO包的IOUtils.copyLarge这个方法解决了。
如果使用的是本地连接时不需要启动服务器,这里与服务器没有关系。