奇怪行为
问题描述:
我的服务器 - 客户端应用程序包含以下模块:奇怪行为
客户端(用Java编写的)连接到服务器并发送的文件;
服务器(用C写)接收文件并发送字符数组消息。
问题是,收到文件后,服务器无法发送消息或客户端无法接收它。
这里是我的服务器应用程序的代码:
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, bytesRead;
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
printf("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;
}
printf("Connection accepted");
//Receive image
while((bytesRead = recv(new_socket, buffer, buffer_len, 0)) > 0)
{
fwrite(buffer, 1, bytesRead, f);
}
fclose(f);
printf("\nReceive finished!");
//Send messsage
char my_message[100];
strcpy(my_message, "Hello World!");
send(new_socket, my_message, strlen(my_message), 0);
closesocket(s);
WSACleanup();
getch();
return 0;
}
而对于客户端应用程序的代码:
public class MyClass
{
public static void main(String[] args)
{
String fileName = "1.jpg", receiveMessage;
File a_file = new File(fileName);
int j;
OutputStream output = null;
InputStream input = null;
ObjectInputStream in = null;
Socket socket = null;
try
{
// Create a socket
socket = new Socket("192.168.0.122", 8888);
FileInputStream fileInputStream = new FileInputStream(fileName);
byte[] buffer = new byte[1000];
int bytesRead = 0;
output = socket.getOutputStream();
input = socket.getInputStream();
while((bytesRead = fileInputStream.read(buffer))>0)
{
output.write(buffer,0,bytesRead);
}
fileInputStream.close();
System.out.println("Send finished!");
input.read(buffer);
System.out.println("Receive finished!");
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
in.close();
output.close();
socket.close();
}
catch(Exception e)
{
}
}
}
}
任何想法来解决这个问题?提前致谢!
答
这是因为你有阻塞插座。当一个套接字被创建时(通过连接或接受)它处于阻塞模式。这意味着如果没有数据接收它将不会返回,从而有效地阻止了调用者。
因此,在收到服务器循环中的最后一个字节后,recv
调用将无限期阻止。
在带winsocket的Windows上,您可以使用ioctlsocket
函数使套接字成为阻塞或非阻塞。链接的引用有一个例子,它显示了热插拔阻塞或非阻塞。
+2
+1 - 除非OP更改协议,否则服务器无法知道所有文件数据都已收到。 –
你的程序中有痕迹。这两个程序在会话期间的输出是什么? – Offirmo
那么,在图像发送后,两个程序都会锁定... – adrian2012