关于java socket编程的小问题

NeverMore2012 2011-05-15 03:39:11
正在完成一个作业,题目是这样的,完成一个简单的tcp程序,有客户端和服务器端,客户端能上传文件到服务器端,我写了一下,但是有问题,我在socket编程的水平是临时抱佛脚的,望好心人能帮我看看哪里写的不对。这个是服务器端代码


package chenyu.ninth.test;

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
public static void main(String args[])throws Exception{
ServerSocket server = null;
Socket client = null;
server = new ServerSocket(8888);
System.out.println("服务器端正在运行,等待客户端连接");
client = server.accept();
InputStream input = client.getInputStream();
BufferedInputStream bis = new BufferedInputStream(input);
OutputStream output = new FileOutputStream("D:\\tupian\\chenting.jpg");
PrintStream out = new PrintStream(client.getOutputStream());
String str ="上传成功";

if(bis!=null&&output!=null){
int temp=0;
while((temp=bis.read())!=-1){
output.write(temp);
}
//out.println(str);
}
out.println(str);
bis.close();
out.close();
output.close();
input.close();
client.close();
server.close();
}
}



然后是客户端代码


package chenyu.ninth.test;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.*;

public class ClientTest {

/**
* @param args
*/
public static void main(String[] args) throws Exception{
Socket client = null;
client = new Socket("localhost",8888);
InputStream input = new FileInputStream("D:\\tupian\\2.gif");
OutputStream output = client.getOutputStream();
PrintStream ps = new PrintStream(output,true);
BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
try{if(input!=null&&ps!=null){
int temp=0;
while((temp=input.read())!=-1){
ps.write(temp);
}
}}catch(Exception e){
System.out.println("源文件不存在");
}
String str = buf.readLine();
System.out.println(str);
buf.close();
output.close();
input.close();
ps.close();
client.close();


}

}






我现在只是做小小的试验,就让他传一张指定目录的图片,运行之后,目标文件夹下是生成了图片,但是我是不能反访问的,它提示我 该文件被另一程序占用,如果我停止运行,会有异常报出,但我看不懂是什么意思,现在图片是能访问的,而且,我在服务器端设置的返回信息在客户端也收不到,问题应该是在服务器端的读文件上面。我把异常贴一下:

Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read(BufferedInputStream.java:235)
at chenyu.ninth.test.TcpServer.main(TcpServer.java:26)

希望能有人回答我。
...全文
173 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
karl1235 2011-05-16
  • 打赏
  • 举报
回复
socket编程 思考的时候客户端和服务器端都要兼顾。

楼主的代码中 client和server建立通信后

客户端第一次读写操作:String str = bfrin.readLine(),客户端一上来就读服务器端消息,阻塞 !
服务器第一次读写操作:ois.readObject(),服务器端一上来就读客户端消息,阻塞 !

客户端和服务器端都阻塞着,互相等待着对方发送消息,所以楼主的程序阻塞了。类似多线程中的死锁。

我发现楼主的代码还有一些问题:

input.read(b)把文件内容读出来了,但未作缓存操作,楼主如何把内容写出去呢
客户端读写流类型有的地方不一致,也许我看错了:-),我的意思是如果是Object流写一定要Object流写,Data流写一定要Data流读。
NeverMore2012 2011-05-15
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 q865617620 的回复:]
悲剧,我也是来看看的,结果没答案。
[/Quote]
我修改了一下,大体算是能上传了,不过还有一个问题
服务器端:

package chenyu.ninth.test;

import java.io.*;
import java.net.*;

public class TcpTestServer {

/**
* @param args
*/
public static void main(String[] args) throws Exception{
ServerSocket server = new ServerSocket(8888);
System.out.println("服务器端等待客户连接...");
Socket client = server.accept();
InputStream input = client.getInputStream();
OutputStream out = client.getOutputStream();
//PrintStream pw = new PrintStream(out);
ObjectInputStream ois = new ObjectInputStream(input);
Target obj = (Target)ois.readObject();
String filename = obj.filename;
byte[] b = obj.b;
int length = obj.len;
File f = new File("D:"+File.separator+filename);//默认上传至d盘根目录。
FileOutputStream output = new FileOutputStream(f);
output.write(b);
output.close();
ois.close();

/*pw.println("服务器收到内容!!!");
pw.close();*/
out.close();
input.close();
client.close();
server.close();


}

}



然后是客户端

package chenyu.ninth.test;

import java.io.*;
import java.net.*;

public class TcpTestClient {
public static void main(String args[])throws Exception{
System.out.println("输入文件的完整路径名,请确保输入正确,因为没有做验证:");
BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
String fileUrl = bfr.readLine();
//String fileUrl = "D:\\haiweiwang\\1.mp3";//在这里输入文件的路径名字
String filename = subStr(fileUrl);

File f = new File(fileUrl);
int length = (int)f.length();
InputStream input = new FileInputStream(f);
byte[] b = new byte[length];
input.read(b);
Target tar = new Target(filename,b,length);


Socket client = new Socket("localhost",8888);
OutputStream output = client.getOutputStream();
InputStream in = client.getInputStream();
//BufferedReader bfrin = new BufferedReader(new InputStreamReader(in));
// String str = bfrin.readLine();
ObjectOutputStream oos = new ObjectOutputStream(output);
oos.writeObject(tar);//使用对象流传入服务器端。
System.out.println("上传完毕");
//System.out.println(str);//接收服务器端返回信息
//bfrin.close();
oos.close();
output.close();
client.close();
input.close();
















}
public static String subStr(String str){
String returnvalue = null;
for(int i=str.length()-1;i>0;i--)
{
if(str.charAt(i)=='\\'){
returnvalue = str.substring(i+1);
break; }
else continue;

}
//System.out.println(returnvalue);
return returnvalue;
}



}



我注释掉的部分是想实现服务器端回复客户端,可是怎么也不能实现。注释掉了倒是可以用,不知道是哪里阻塞了,不执行下去,还是等待高人解决
q865617620 2011-05-15
  • 打赏
  • 举报
回复
悲剧,我也是来看看的,结果没答案。
NeverMore2012 2011-05-15
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 healer_kx 的回复:]
嗯。我了解了,我试验了一下。
逻辑基本都OK,就是最后传输完毕后。退出循环的条件。
[/Quote]
研究的怎么样啦?
healer_kx 2011-05-15
  • 打赏
  • 举报
回复
嗯。我了解了,我试验了一下。
逻辑基本都OK,就是最后传输完毕后。退出循环的条件。

环境:Windows XP SP3、 VC++ 6.0、 Windows 2003 SDK 使用步骤: 1、下载解压之后,使用VC++ 6.0打开两个工程:一个是SocketServer和一个ClientSocket工程。 2、首先运行服务器端工程,选默认的端口1008 3、然后运行客户端工程,选默认的端口1008和默认的服务器地址 4、再运行多个客户端进程 5、如果一切正常,可以每个客户端的消息发送,我们可以在服务端和各个客户端同步看到消息 实现一个服务器对多个客户端的关键是,在服务端的使用集合CPtrList类用保存客户端的socket对象,思想与Java中的编程思想一样,只不过Java中会使用多线程技术,在Vector集合保存客户端的socket对象,而MFC框架提供了CSocket类,它是一个异步通信的类,所以看上去代码比较Java的多线程代码简单的实现了一个对多的即时通讯功能。另外,MFC提供了CSocketFile类和CArchive类与CSocket类实现了C++的网络通讯编程功能。 本示例注释非常详细,所有的辅助类都放一个util目录中,然后在工程中分了一个目录来管理这些辅助类,使用代码非常清晰。手动书写部分的代码是按Java的规范书写,当然其它代码由IDE生成的,所以是MS的风格,所以当你看代码时,只要是使用“骆驮命名法”的方法都是本人书写的功能性代码。 参看的思路:在服务端要从回调方法onAccept读起;而客户端代码主要从OnSendButton方法读起,即可理解整个代码的意思。 阅读对象:具有JavaSocket编程经验的人员,并且希望能够书写出比Java效率更高的即时通讯程序的人员

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧