结束客户端和服务器套接字之间交换的“消息”

时间:2014-12-08 15:41:15

标签: java sockets winsock

Java服务器套接字

在以下代码中: https://docs.oracle.com/javase/tutorial/networking/sockets/examples/KnockKnockServer.java

import java.net.*;
import java.io.*;

public class KnockKnockServer {
    public static void main(String[] args) throws IOException {

        if (args.length != 1) {
            System.err.println("Usage: java KnockKnockServer <port number>");
            System.exit(1);
        }

        int portNumber = Integer.parseInt(args[0]);

        try ( 
            ServerSocket serverSocket = new ServerSocket(portNumber);
            Socket clientSocket = serverSocket.accept();
            PrintWriter out =
                new PrintWriter(clientSocket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
                new InputStreamReader(clientSocket.getInputStream()));
        ) {

            String inputLine, outputLine;

            // Initiate conversation with client
            KnockKnockProtocol kkp = new KnockKnockProtocol();
            outputLine = kkp.processInput(null);
            out.println(outputLine);

            while ((inputLine = in.readLine()) != null) {
                outputLine = kkp.processInput(inputLine);
                out.println(outputLine);
                if (outputLine.equals("Bye."))
                    break;
            }
        } catch (IOException e) {
            System.out.println("Exception caught when trying to listen on port "
                + portNumber + " or listening for a connection");
            System.out.println(e.getMessage());
        }
    }
}

当服务器将其响应发送到客户端套接字时,它使用“println()”方法(第63行)写入“PrintWriter”“out”。

  • 我尝试过使用“print()”方法。
  • 在“println()”案例中,客户端套接字正确接收消息。
  • 在“print()”的情况下,客户端套接字不会收到任何内容。
  • 这是正常的吗?
  • 是否需要在邮件末尾发送EOFCR LF(在我的情况下)(10和13个ASCII字符)?
  • 是否记录在某处?

的Winsock

在以下代码中: http://msdn.microsoft.com/en-us/library/windows/desktop/ms737591%28v=vs.85%29.aspx

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>


// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")


#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"

int __cdecl main(int argc, char **argv) 
{
    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
                    *ptr = NULL,
                    hints;
    char *sendbuf = "this is a test";
    char recvbuf[DEFAULT_BUFLEN];
    int iResult;
    int recvbuflen = DEFAULT_BUFLEN;

    // Validate the parameters
    if (argc != 2) {
        printf("usage: %s server-name\n", argv[0]);
        return 1;
    }

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
    if ( iResult != 0 ) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    // Attempt to connect to an address until one succeeds
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
            ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }

        // Connect to server.
        iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }

    // Send an initial buffer
    iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    printf("Bytes Sent: %ld\n", iResult);

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // Receive until the peer closes the connection
    do {

        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if ( iResult > 0 )
            printf("Bytes received: %d\n", iResult);
        else if ( iResult == 0 )
            printf("Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());

    } while( iResult > 0 );

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}

使用“send()”方法。

  • 是否在作为参数传递的消息末尾隐式发送EOF(例如CR LF序列)到服务器套接字?
  • 是否记录在某处?
  • 它是套接字实现的一部分吗?
  • 请注意,我没有在邮件末尾添加EOF(例如CR LF)。
  • 我结束了带有'\ 0'字符的消息。

当一个“消息”(一个字符数组)从一个套接字端点发送到另一个套接字端点时,该消息是否必须以某种EOF结束?现在我觉得它没有。

2 个答案:

答案 0 :(得分:1)

一般不需要在Java套接字通信中发送EOF标志,但是 如果您的客户端使用InputStream.readLine()来读取服务器的答案,那么这是正常的,因为 readLine()阻塞,直到完全读取一行(直到找到\ n \ r或\ r \ n)或服务器关闭套接字。
但在此示例中,服务器未关闭套接字,因为服务器正在等待客户端应答,如果客户端正在等待行结束,则会出现死锁。

答案 1 :(得分:1)

  

当服务器将其响应发送到客户端套接字时,它会写入&#34; PrintWriter&#34; &#34;列&#34;使用&#34; println()&#34;方法

PrintWriter是行缓冲的。见Javadoc。

  

我尝试过使用&#34; print()&#34;方法改为。

如果你不写一条线,它就不会冲洗。之后致电flush()。但是你不应该在网络上使用PrintWriter,因为它会吞下您需要了解的异常。使用BufferedWriter

  

在&#34; println()&#34; case,客户端套接字正确接收消息。

因为它是行缓冲的,所以有一个自动刷新。

  

在&#34; print()&#34;如果客户端套接字没有收到任何内容。

因为它是行缓冲的,所以没有自动刷新。

  

这是正常的吗?

  

是否需要在邮件末尾发送EOF,CR LF(在我的情况下)(10和13个ASCII字符)?

没有

  

是否记录在某处?

是的,在PrintWriter的Javadoc中。