我试图通过TCP套接字和服务器将实时麦克风录制传输到服务器,以将输入流写入文件。 建立了连接,但过了一段时间后,我的客户端出现连接拒绝错误。
服务器代码:
public class auServer extends Thread{
private static ServerSocket serverSocket;
private static int port = 3333;
public void run()
{
System.out.println("init success");
while(true)
{
try
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
Socket clientSoc = serverSocket.accept();
System.out.println("Waiting for client on port " +serverSocket.getLocalPort() + "...");
System.out.println("Just connected to " + clientSoc.getRemoteSocketAddress());
InputStream in = clientSoc.getInputStream();
while(in!=null)
{
writeToFile(in);
}
System.out.println("socket");
clientSoc.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
System.out.println("some io");
break;
} catch (Exception e) {
System.out.println("some e");
e.printStackTrace();
}
}
}
private void writeToFile(InputStream in) throws IOException {
// Write the output audio in byte
String filePath = "8k16bitMono1.wav";
short sData[] = new short[1024];
byte[] bData = IOUtils.toByteArray(in);
FileOutputStream os = null;
try {
os = new FileOutputStream(filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("Short wirting to file" + sData.toString());
try {
os.write(bData, 0, 2048);
} catch (IOException e) {
e.printStackTrace();
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try
{
Thread serverThread = new auServer();
serverThread.run();
System.out.println("runing");
}catch(IOException e){
e.printStackTrace();
}
}
}
和客户:
private void streamData(byte[] bData) throws UnknownHostException, IOException, InterruptedException { //bData is byte array to transmit
Thread.sleep(500);
Socket client = new Socket("10.221.40.41",3333);
OutputStream outToServer = client.getOutputStream();
outToServer.write(bData);
if(!isRecording)
client.close();
}
可能是什么问题? 提前谢谢。
答案 0 :(得分:15)
我会逐条评论你的代码。
private static ServerSocket serverSocket;
没有理由不这样做。
while(true)
{
try
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
最后两行应该在循环之前。这是连接拒绝的原因,它也会导致您没有提及BindExceptions
。目前还不清楚为什么需要超时。
Socket clientSoc = serverSocket.accept();
System.out.println("Waiting for client on port " +serverSocket.getLocalPort() + "...");
不,你不是。他已经联系了。你在之前等待 accept().
System.out.println("Just connected to " + clientSoc.getRemoteSocketAddress());
InputStream in = clientSoc.getInputStream();
while(in!=null)
循环和测试都是徒劳的。变量最初不是null,并且它不可能变为null。循环是徒劳的,因为writeToFile()
方法完全耗尽了输入流,所以永远不会有任何东西要阅读。这将导致垃圾数据,你还没有提到。
{
writeToFile(in);
}
System.out.println("socket");
毫无意义的消息。
clientSoc.close();
accept()
之后的行中的所有代码都应该在一个单独的线程中执行。接受循环除了接受连接和启动线程之外什么都不做。
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
这里的时间是accept()
,因为侦听套接字是您设置超时的唯一套接字。我怀疑你需要这个。
break;
}catch(IOException e)
{
e.printStackTrace();
System.out.println("some io");
另一个徒劳的信息。
break;
} catch (Exception e) {
System.out.println("some e");
还有一个。当你收到异常时,打印异常。不是你自己设计的一些徒劳的信息。否则调试就变成了猜测游戏。
e.printStackTrace();
}
}
}
private void writeToFile(InputStream in) throws IOException {
// Write the output audio in byte
String filePath = "8k16bitMono1.wav";
short sData[] = new short[1024];
未使用。删除。
byte[] bData = IOUtils.toByteArray(in);
不要使用它。它浪费空间并增加延迟。请参阅下面的正确解决方案。
FileOutputStream os = null;
try {
os = new FileOutputStream(filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
技术差。这个catch
位置错误。取决于try
块中代码成功的代码应位于同一try
块内。目前您正在考虑这个try-catch
,好像从未发生过异常,这将在下面的代码中导致NullPointerException
。
System.out.println("Short wirting to file" + sData.toString());
另一个毫无意义的消息。拼写错误; sData
中没有任何内容;无论内容如何,sData.toString()
都不会打印任何有用的内容;并且不正确,因为你根本没有写sData
。
try {
os.write(bData, 0, 2048);
这准确写入2048个字节,无论读取的数量是多少,都可以更少或更多。如果它少了会抛出一个ArrayIndexOutOfBoundsException
或类似的,我希望在第二次调用时看到它,虽然你还没有提到它,因为在第二次和后续的调用中数组应该是零长度,如果有的话。它应该是一个循环,一般形式:
int count;
byte[] buffer = new byte[8192]; // or more if you like
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
返回您的代码:
} catch (IOException e) {
e.printStackTrace();
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try
{
Thread serverThread = new auServer();
serverThread.run();
这将运行线程的run()
方法。它不会启动一个线程。它应该是serverThread.start().
System.out.println("runing");
拼错。在您修复上述启动/运行问题之前,在服务器的run()
方法退出之前,您才会看到此消息。
和客户:
private void streamData(byte[] bData) throws UnknownHostException, IOException, InterruptedException { //bData is byte array to transmit
Thread.sleep(500);
毫无意义的。去掉。不要把睡眠放入网络代码中。
Socket client = new Socket("10.221.40.41",3333);
不要为每个缓冲区创建新连接。在客户的生命中使用相同的连接。
OutputStream outToServer = client.getOutputStream();
outToServer.write(bData);
if(!isRecording)
client.close();
这应该是无条件的,它应该在其他地方,以及套接字的创建。
可能是什么问题?
问题。多个。多。见上文。
答案 1 :(得分:3)
必须在循环外部创建serversocket。 对于并行连接,您需要为每个连接启动一个线程。
还将超时应用于已建立的连接。 serverSocket上的超时将在超时后结束,这在服务器中不是你想要的。
...
public void run() {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(port);
} catch (Exception ex) {
ex.printStackTrace();
return;
}
System.out.println("init success");
while (true) {
try {
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
final Socket clientSoc = serverSocket.accept();
clientSoc.setSoTimeout(10000);
System.out.println("Just connected to " + clientSoc.getRemoteSocketAddress());
new Thread() {
public void run() {
try {
InputStream in = clientSoc.getInputStream();
writeToFile(in);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
clientSoc.close();
} catch (Exception ignore) {
}
}
}
}.start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
...
答案 2 :(得分:3)
我猜你的客户端是一个Android应用程序。有一次,我尝试通过套接字连接读取和写入数据到Android应用程序。最后,我使用adb(android调试器桥)完成了它。
可以说,有一个java应用程序创建一个端口号为1992的Socket
。还有一个android应用程序,它创建一个端口号为1993的ServerSocket
。
这是真正的交易!
在开始运行应用程序之前,您需要在adb shell中执行以下命令(或者您可以在cmd / terminal中找到您的adb并执行命令)
adb forward tcp:1992 tcp:1993
转发端口后,您可以使用套接字的IO流将Java应用程序中的数据写入Android应用程序,反之亦然。
桌面应用程序代码段:
while (flag) {
try {
final Socket socket = new Socket("localhost", 1992);
new Thread(){
@Override
public void run() {
while (flag) {
try {
new PrintWriter(socket.getOutputStream(), true).println(new Date().toString());
} catch (IOException ex) {
break;
}
}
}
}.start();
} catch (IOException ex) {
// need port-forwarding
}
}
Android应用程序代码段:
while (flag) {
try {
final Socket socket = new ServerSocket(1993).accept();
new AsyncTask<Void, Void, Void>() {
@Override
public Void doInBackground(Void... params) {
while (flag) {
try {
String line = new BufferedReader(new InputStreamReader(socket.getInputStream())).readLine();
Log.d("", line);
} catch (IOException ex) {
return null;
}
}
return null;
}
}.execute();
} catch (IOException ex) {
break;
}
}
您可以将音频转换为字节数组并将其写入输出流。希望我的回答很有用。
答案 3 :(得分:1)
我找到了解决方案。 问题实际上是由于错误编码的流阻塞了网络I / O.
我错过的是
InputStream in = clientSoc.getInputStream();
DataInputStream DataIn =new DataInputStream(in)
while(DataIn!=null)
{
writeToFile(DataIn);
}
和客户端
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.write(sData);