简体   繁体   中英

Can I communicate between Java and C# using just sockets?

更具体地说,如果一台计算机有一个服务器(一个java.net.ServerSocket实例),我可以使用 C# System.Net.Sockets.Socket实例连接到它吗?

The main issue is that you need to be very careful with the encoding of the data that you send and receive. Here is a pair of programs that work together. The C# client sends a string, by first sending its length as an integer, and then sending the bytes of the string itself. The Java server reads the length, then reads the message and prints an output to the console. Then composes an echo message, computes its length, extracts the bytes and sends it back to the C# client. The client reads the length, the message and prints an output. There should be a way to avoid all the bitwise stuff, but honestly I'm a little rusty with this stuff, especially on the Java side.

A Java server:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class JavaSocket {

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

        ServerSocket serverSocket = new ServerSocket(4343, 10);
        Socket socket = serverSocket.accept();
        InputStream is = socket.getInputStream();
        OutputStream os = socket.getOutputStream();

        // Receiving
        byte[] lenBytes = new byte[4];
        is.read(lenBytes, 0, 4);
        int len = (((lenBytes[3] & 0xff) << 24) | ((lenBytes[2] & 0xff) << 16) |
                  ((lenBytes[1] & 0xff) << 8) | (lenBytes[0] & 0xff));
        byte[] receivedBytes = new byte[len];
        is.read(receivedBytes, 0, len);
        String received = new String(receivedBytes, 0, len);

        System.out.println("Server received: " + received);

        // Sending
        String toSend = "Echo: " + received;
        byte[] toSendBytes = toSend.getBytes();
        int toSendLen = toSendBytes.length;
        byte[] toSendLenBytes = new byte[4];
        toSendLenBytes[0] = (byte)(toSendLen & 0xff);
        toSendLenBytes[1] = (byte)((toSendLen >> 8) & 0xff);
        toSendLenBytes[2] = (byte)((toSendLen >> 16) & 0xff);
        toSendLenBytes[3] = (byte)((toSendLen >> 24) & 0xff);
        os.write(toSendLenBytes);
        os.write(toSendBytes);

        socket.close();
        serverSocket.close();
    }
}

AC# client:

using System;
using System.Net;
using System.Net.Sockets;

namespace CSharpSocket
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            string toSend = "Hello!";

            IPEndPoint serverAddress = new IPEndPoint(IPAddress.Parse("192.168.0.6"), 4343);

            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            clientSocket.Connect(serverAddress);

            // Sending
            int toSendLen = System.Text.Encoding.ASCII.GetByteCount(toSend);
            byte[] toSendBytes = System.Text.Encoding.ASCII.GetBytes(toSend);
            byte[] toSendLenBytes = System.BitConverter.GetBytes(toSendLen);
            clientSocket.Send(toSendLenBytes);
            clientSocket.Send(toSendBytes);

            // Receiving
            byte[] rcvLenBytes = new byte[4];
            clientSocket.Receive(rcvLenBytes);
            int rcvLen = System.BitConverter.ToInt32(rcvLenBytes, 0);
            byte[] rcvBytes = new byte[rcvLen];
            clientSocket.Receive(rcvBytes);
            String rcv = System.Text.Encoding.ASCII.GetString(rcvBytes);

            Console.WriteLine("Client received: " + rcv);

            clientSocket.Close();
        }
    }
}

I figure how to loop this method so you can send client message over and over again. Let me know if you found this useful. I build this on Eclipse with Export Ant script. I will include ant script as well

package lineage;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;


public class l2protector {
    public static void main(String[] args) throws IOException {
        boolean runserver = true;
        ServerSocket serverSocket = new ServerSocket(1040, 10);
        Socket socket = serverSocket.accept();
        InputStream is = socket.getInputStream();
        OutputStream os = socket.getOutputStream();
        do
        {
            try {
                serverSocket = new ServerSocket(1040, 10);
                socket = serverSocket.accept();
                is = socket.getInputStream();
                os = socket.getOutputStream();
                // Receiving
                byte[] lenBytes = new byte[4];
                is.read(lenBytes, 0, 4);
                int len = (((lenBytes[3] & 0xff) << 24) | ((lenBytes[2] & 0xff) << 16) |
                          ((lenBytes[1] & 0xff) << 8) | (lenBytes[0] & 0xff));
                byte[] receivedBytes = new byte[len];
                is.read(receivedBytes, 0, len);
                String received = new String(receivedBytes, 0, len);
                if(received != null) {
                    System.out.println("Server received: " + received);
                }
                // Sending
                String toSend = "Echo: " + received;
                byte[] toSendBytes = toSend.getBytes();
                int toSendLen = toSendBytes.length;
                byte[] toSendLenBytes = new byte[4];
                toSendLenBytes[0] = (byte)(toSendLen & 0xff);
                toSendLenBytes[1] = (byte)((toSendLen >> 8) & 0xff);
                toSendLenBytes[2] = (byte)((toSendLen >> 16) & 0xff);
                toSendLenBytes[3] = (byte)((toSendLen >> 24) & 0xff);
                os.write(toSendLenBytes);
                os.write(toSendBytes);
                socket.close();
            }
            catch(Exception e) {
                serverSocket.close();
            }
            
        }
        while(runserver);
        serverSocket.close();
    }
}

Ant Script:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- WARNING: Eclipse auto-generated file.
              Any modifications will be overwritten.
              To include a user specific buildfile here, simply create one in the same
              directory with the processing instruction <?eclipse.ant.import?>
              as the first entry and export the buildfile again. --><project name="AntiCheat" default="dist" basedir=".">
    <description>
    simplest example build file
  </description>
    <!-- set global properties for this build -->
    <property name="src" location="src" />
    <property name="build" location="build" />
    <property name="dist" location="dist" />
    <property name="version" value="1.0" />
 
    <target name="init">
        <!-- Create the time stamp -->
        <tstamp />
        <!-- Create the build directory structure used by compile -->
        <mkdir dir="${build}" />
    </target>
 
    <target name="compile" depends="init" description="compile the source">
        <!-- Compile the java code from ${src} into ${build} -->
        <javac srcdir="${src}" destdir="${build}" />
    </target>
 
    <target name="dist" depends="compile" description="generate the distribution">
        <buildnumber />
        <!-- Create the distribution directory -->
        <mkdir dir="${dist}/lib" />
 
        <!-- Put everything in ${build} into the MyApplication-${version}.${build.number}.jar -->
        <jar destfile="${dist}/lib/MyApplication-${version}.${build.number}.jar" basedir="${build}" />
    </target>
 
    <target name="clean" description="clean up">
        <!-- Delete the ${build} and ${dist} directory trees -->
        <delete dir="${build}" />
        <delete dir="${dist}" />
    </target>
</project>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM