有一个问题一直不太明白,我想写一个客户端通过socket流向服务端传输文件的程序。 我想先传输文件名,文件长度,再传输文件内容。可是如果在客户端向流中依次写入这三个部分,那么服务端如何在流中区分开文件名,文件长度和文件内容?
------解决方案--------------------
这个涉及在并发的时候有问题吧
比如两个客户端同时发,
可能会有错。
------解决方案--------------------
当午理解错了,我说的是作为一个流,三部分之间用分隔符隔开,或者就固定长度,比如文件名固定为256字节,长度固定为10字节,剩下的都是内容。
------解决方案--------------------
楼主我建议你把要通过socket传的东西封装成一个类,文件的大小,名字都做为整个类的变量,将这个类序列化,通过ObjectOutputStream流来写入,这样就不会出现你说的问题了
------解决方案--------------------
楼主问的问题实际上是“通信协议”的问题。
socket 通信程序一般都是需要制定通信协议的,只不过有时候比较简单,就不用特别描述了(比如,如果只传文件内容,那么,不用特别去讲通信协议是怎么怎么样的了。这时候,并不是没有通信协议,而是有一个特别简单的协议)。
对于楼主说的这种情况,就需要对通信协议做一个明确描述了。至于具体内容是什么,完全可以自己定义。比如:“从第一个字节开始,是一个 null-terminated 的 UTF8 字符串,表示文件名;紧跟着 8 个字节表示文件的字节长度(高位在前,低位在后);然后紧跟着的是文件内容,字节数是前面确定的文件长度值”。
------解决方案--------------------
发段代码
服务器
import java.io.*;
import java.net.*;
import java.util.*;
import enroll.EnrollInfo;
public class Main
{
public static void main(String[] args)
{
try
{
//创建连接
ServerSocket socket = new ServerSocket(7002);
while(true)
{
int counter=1;
//连接
Socket incoming=socket.accept();
System.out.println(counter);
Runnable r=new ThreadeEchoHand(incoming,counter);
Thread t=new Thread(r);
t.start();
counter++;
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
class ThreadeEchoHand implements Runnable//线程类
{
private Socket incoming;
private int counter;
public ThreadeEchoHand(Socket incoming, int counter)
{
this.incoming=incoming;
this.counter=counter;
}
public void run()
{
try
{
try
{
//输入流和输出流连接incoming
InputStream inStream=incoming.getInputStream();
OutputStream outStream=incoming.getOutputStream();
//用输入流得到数据
ObjectInputStream inobj=new ObjectInputStream(inStream);
//用输出流输出数据
ObjectOutputStream outobj=new ObjectOutputStream(outStream);
try
{
//读一段数据
EnrollInfo n=(EnrollInfo)inobj.readObject();
System.out.println(n.toString());
//System.out.println(incoming.getLocalPort());
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
finally{incoming.close();}//关闭流
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
客户端
import java.io.*;
import java.net.*;
import java.sql.*;
import enroll.EnrollInfo;
public class Na
{
public Na()
{
ObjectOutputStream o=null;
Socket socket1=null;
try {
socket1 = new Socket( "127.0.0.1 ", 7002);
//输入流和输出流连接incoming
OutputStream outStream=socket1.getOutputStream();
o=new ObjectOutputStream(outStream);
EnrollInfo nn=new EnrollInfo( "name ", "asas ",new Date(19820208), "3423 ", "3123 ", "324 ", "3424 ", "4234 ");
o.writeObject(nn);
o.flush();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//关闭流
finally{try {
o.close();
socket1.close();