我正在研究客户端服务器架构,我只是初学者。这里我的服务器是C,客户端是Java,我想从C服务器向Java客户端发送大小约为10-20 MB的二进制/数据库(.db)/映像文件。但是在实现以下代码时数据会丢失:
服务器端C代码是:
int sockfd, newsockfd, portno, clilen;
struct sockaddr_in serv_addr, client_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
strcpy(message,"Error opening socket");
eFlag = 1;
send_message(message);
}
bzero((char *)&serv_addr, sizeof(serv_addr));
portno = 6789;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if(bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
strcpy(message,"Error on binding");
eFlag = 1;
send_message(message);
}
listen(sockfd, 5);
clilen = sizeof(client_addr);
newsockfd = accept(sockfd, (struct sockaddr *)&client_addr, &clilen);
if(newsockfd < 0)
{
strcpy(message,"Error on accept");
eFlag = 1;
send_message();
exit(4);
}
void send_file()
{
buffer = (char *)malloc(sizeof(char)*lSize);
result = fread(buffer, sizeof(char), lSize, fp);
printf("\n\n########## data read into buffer successfully #######");
if(newsockfd)
{
n = send(newsockfd, buffer, lSize);
printf("\n\n$$$$$$$$ Data sent successfully $$$$$");
strcpy(message,"Data sent successfully");
send_message(message);
}
else
{
strcpy(message, "Error writing on socket");
send_message(message);
}
sleep(sleepTime);
sleepTime = (int) (sleepTime*1.02);
free(buffer);
}
而且,我的客户端Java代码是:
final int PORT_NO = 6789;
final String Server_name = "192.133.133.1";
Socket m_socket = null;
String str;
int ch;
try {
if(m_socket == null)
m_socket = new Socket(Server_name, PORT_NO);
if(m_socket == null)
System.out.println("Unable to open the socket");
DataInputStream dis = new DataInputStream(m_socket.getInputStream());
PrintStream ps = new PrintStream(m_socket.getOutputStream());
DataInputStream ds = new DataInputStream(System.in);
while(true)
{
System.out.println("1. Synchronize");
System.out.println("2. Exit");
System.out.println("Enter your choice...");
str = ds.readLine();
ch = Integer.parseInt(str);
switch(ch)
{
case 1:
ps.println("<message action='buttonpress' value='synchronize' />");
System.out.println("avilable data to read is:"+dis.available());
FileOutputStream fos = new FileOutputStream("mukul.db");
byte data[] = new byte[102400]; //100 Kb byte array
dis.read(data);
String str_data = new String(data);
str_data = str_data.trim();
data = str_data.getBytes();
fos.write(data);
fos.close();
break;
这里只读取部分数据,即大约10 kb或更少。
我只是这些帖子的初学者,我的代码可能很麻烦,所以请忽略发布中的所有错误。
所以请告诉我如何在不丢失数据的情况下在此客户端 - 服务器架构中接收1 MB / 10 MB的数据。
如果我在C代码中使用“sendfile(out_fp,in_fp,pos,len)”方法而不是“send()”,该怎么办?此方法发送文件句柄。那么Java中相应的函数将捕获文件句柄。
提前谢谢。
答案 0 :(得分:1)
您滥用send()/ recv()函数。由于内核中可能存在限制,send()和recv()不需要发送您请求的数据。您必须反复调用send()直到所有数据都被推送完毕。
e.g:
int sent = 0;
int rc;
while ( sent < should_send )
{
rc = send(sock, buffer + sent, should_send - sent, 0);
if ( rc <= 0 ) // Error or hangup
// do some error handling;
sent += rc;
}
答案 1 :(得分:1)
Java方面,
int lent2 = 0;
int LengthToReceive = 102400;
char[] chTemp = new char[LengthToReceive];
while (true) {
int readlength = bufferedreader.read(chTemp, lent2,LengthToReceive - lent2);
if(readlength==-1){
break;
}
lent2 += readlength;
if (lent2 >= LengthToReceive) {
flag = false;
break;
}
}
答案 2 :(得分:0)
调用m_socket = new Socket(...)
后,m_socket不能为该行。它将抛出异常或将Socket
分配给m_socket,永远不为null。所以这个测试毫无意义。
调用readLine()
后,必须检查空返回值,这意味着EOS,这意味着另一端已关闭连接,这意味着您必须退出读取循环并关闭套接字。
正如Javadoc所说,InputStream.available()
不应该用于测试EOS。它的合同是返回可以无阻塞地读取的字节数。这很少与通过套接字传入文件的长度相同。您必须继续读取插座,直到EOS:
int count;
byte[] buffer = new byte[8192];
while ((count = in.read(buffer)) > 0)
out.write(buffer, 0, count);
如果您的发送端在完成发送文件时没有关闭套接字,则必须让它在文件之前发送文件长度,并修改上面的循环以准确读取该字节数。