[英]Connection reset by peer: socket write error c++ - java
我正在尝试编写用于文件传输的服务器-客户端应用程序。 客户端用Java编写,服务器用C ++编写。
不幸的是我有以下错误:
java.net.SocketException:连接被同级重置:套接字写入错误”
这是我给客户的代码:
import java.io.*;
import java.net.Socket;
public class Proba_binar
{
public static void main(String[] args)
{
byte[] buffer = null;
byte[] auxByte = new byte[1000];
String fileName = "1.jpg";
File a_file = new File(fileName);
try
{
// Create a socket
Socket socket = new Socket("192.168.14.146", 8888);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// Read file
FileInputStream fis = new FileInputStream(fileName);
int length = (int)a_file.length();
buffer = new byte[length];
fis.read(buffer);
fis.close();
// Send file length
System.out.println("length = " + Integer.toString(length));
out.write(Integer.toString(length) + "\n");
out.flush();
// Send file
int imageSize = buffer.length;
char[] auxChar = new char[1000];
int nr_transf = imageSize / 1000;
int rest_byte = imageSize % 1000;
System.out.println("nr_transf = " + nr_transf);
for(int j = 0; j < nr_transf; j++)
{
// send series of 1000 bytes
for(int i = 0; i < 1000; i++)
{
auxChar[i] = (char)buffer[j*1000+i];
auxByte[i] = buffer[j*1000+i];
}
out.write(auxChar);
out.flush();
}
// send last bytes
for(int i = 0; i < rest_byte; i++)
{
auxChar[i] = (char)buffer[1000*nr_transf+i];
auxByte[i] = buffer[1000*nr_transf+i];
}
out.write(auxChar, 0, rest_byte);
out.flush();
out.close();
in.close();
socket.close();
System.out.println("Transfer finished!");
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
和服务器的代码:
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET s , new_socket;
struct sockaddr_in server , client;
int c, bytecount, nr_transf, rest_byte, i;
int recv_size, file_size;
char message[1000];
char buffer[1000];
int buffer_len = 1000;
FILE *f = fopen("out.jpg", "wb");
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
getch();
return 0;
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
//Bind
if(bind(s, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
getch();
return 0;
}
puts("Bind done");
//Listen to incoming connections
listen(s, 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
new_socket = accept(s, (struct sockaddr*)&client, &c);
if (new_socket == INVALID_SOCKET)
{
printf("accept failed with error code : %d", WSAGetLastError());
getch();
return 0;
}
puts("Connection accepted");
//Receive FILE DIMENSION from client
if((recv_size = recv(new_socket, message, 1000, 0)) == SOCKET_ERROR)
{
puts("recv failed");
getch();
}
message[recv_size] = '\0';
file_size = atoi(message);
printf("\nfile_size = %d", file_size);
nr_transf = file_size / 1000;
rest_byte = file_size % 1000;
//Receive FILE from client
for(i = 0; i < nr_transf; i++)
{
// receive 1000 bytes
if((bytecount = recv(new_socket, buffer, buffer_len, 0)) == SOCKET_ERROR)
{
printf("Receive failed auxChar");
getch();
return 0;
}
fwrite(buffer, 1, buffer_len, f);
}
// receive last bytes
if((bytecount = recv(new_socket, buffer, rest_byte, 0)) == SOCKET_ERROR)
{
printf("Receive failed rest_byte");
getch();
return 0;
}
fwrite(buffer, 1, rest_byte, f);
fclose(f);
printf("Receive finished!");
closesocket(s);
WSACleanup();
getch();
return 0;
}
我用Java制造了等效的服务器,并且运行良好。 我不知道c ++版本中存在什么问题。 提前致谢!
recv()
不保证它将读取所有请求的字节:
...调用recv将返回当前可用的尽可能多的数据-达到指定缓冲区的大小...
这意味着for
/ recv
循环的结构不正确,很可能是服务器认为自己已读取所有数据但尚未读取所有数据。 这导致服务器在客户端发送所有数据之前关闭套接字,从而导致Java客户端报告错误。
recv
循环的示例(未经测试)重组:
int totalBytesRead = 0;
int bytesRead;
while (totalBytesRead < file_size)
{
if((bytesRead = recv(new_socket, buffer, buffer_len, 0)) == SOCKET_ERROR)
{
/* Handle failure. */
break;
}
if (bytesRead != fwrite(buffer, 1, bytesRead, f))
{
/* Handle failure. */
break;
}
totalBytesRead += file_size;
}
请记住,连接的套接字基于流,使用mutilple send()
并不意味着匹配的recv()
会读取与发送时相同的“块”中的数据。 除了已经提到的数据内容检索错误外,这同样适用于读取文件大小。 无法保证将读取整个文件的大小。
我建议设计一个简单的协议,以确保正确读取不同类型的数据。 例如,客户端发送:
<文件大小> \\ n <文件内容>
服务器读取所有数据,直到换行符为止,并将其转换为文件大小。 然后,服务器肯定会知道它具有正确的文件大小。 然后,服务器从套接字读取file_size
字节。 最后,服务器响应以指示成功或失败:
成功\\ n
客户端读取换行符以获取响应。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.