I am trying to create an asynchronous socket server with using c#
The client socket is written in Java
The problem is that when the client connects to the server for the second time, it cannot read the message from client
I also noticed that this happens when I try to send data to the server specifically from the getKey()
function
The result of the first and second connections:
server code:
public class SocketServer : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8899);
Socket socketServer = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socketServer.Bind(ipEndPoint);
socketServer.Listen(100);
while (!stoppingToken.IsCancellationRequested)
{
Socket socketClient = await socketServer.AcceptAsync();
Console.WriteLine("Client connected");
processClientTearOff(socketClient);
}
}
async Task processClientTearOff(Socket socket)
{
using (var client = new Client(socket))
await client.ProcessAsync();
}
class Client : IDisposable
{
Socket socketClient;
public Client(Socket socketClient)
{
this.socketClient = socketClient;
}
public void Dispose()
{
Console.WriteLine("Client dispose");
if (socketClient != null)
{
socketClient.Disconnect(false);
socketClient.Shutdown(SocketShutdown.Both);
socketClient.Close();
socketClient.Dispose();
socketClient = null;
}
}
bool SocketConnected()
{
if (socketClient == null || !socketClient.Connected)
return false;
bool part1 = socketClient.Poll(1000, SelectMode.SelectRead);
bool part2 = (socketClient.Available == 0);
if (part1 && part2)
return false;
else
return true;
}
public async Task ProcessAsync()
{
while (SocketConnected())
{
await JavaClient();
}
}
async Task JavaClient()
{
string a = await ReadUTF();
WriteUTF(a);
}
async Task WriteUTF(string data)
{
Console.WriteLine($"[ ] Write : {data}");
byte[] bytes = Encoding.UTF8.GetBytes(data);
byte[] bytesLength = BitConverter.GetBytes(bytes.Length);
Array.Reverse(bytesLength, 0, bytesLength.Length);
await socketClient.SendAsync(bytesLength, SocketFlags.None);
await socketClient.SendAsync(bytes, SocketFlags.None);
}
async Task<string> ReadUTF()
{
byte[] buf = new byte[4];
int bytesRec = await socketClient.ReceiveAsync(buf, SocketFlags.None);
int totalBytesRec = 0;
StringBuilder builder = new StringBuilder();
if (4 == bytesRec)
{
int len = ReverseInt(buf);
buf = new byte[len];
do
{
bytesRec = await socketClient.ReceiveAsync(buf, SocketFlags.None);
totalBytesRec = bytesRec;
builder.Append(Encoding.UTF8.GetString(buf, 0, bytesRec));
} while (totalBytesRec < len && bytesRec > 0);
}
string result = builder.ToString();
Console.WriteLine($"[ ] Read : {result}");
return result;
}
int ReverseInt(byte[] array)
{
var bytes = new byte[array.Length];
array.CopyTo(bytes, 0);
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToInt32(bytes, 0);
}
}
}
client code:
public static void main(String[] args)
{
try
{
Socket s = new Socket(IP, PORT);
final DataInputStream in = new DataInputStream(s.getInputStream());
final DataOutputStream out = new DataOutputStream(s.getOutputStream());
String key = getKey(); // key = A5E5F7B526C52014323E17B1BAEA406C
writeUTF(out, key);
System.out.println(readUTF(in));
}
catch (Exception exception)
{
exception.printStackTrace();
}
}
public static String getKey() {
try {
MessageDigest hash = MessageDigest.getInstance("MD5");
String s = System.getenv("COMPUTERNAME") System.getenv("PROCESSOR_IDENTIFIER")
System.getenv("PROCESSOR_ARCHITECTURE") System.getenv("NUMBER_OF_PROCESSORS");
return bytesToHex(hash.digest(s.getBytes()));
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
public static void writeUTF(DataOutputStream out, String str) throws Exception {
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
out.writeInt(bytes.length);
out.write(bytes);
}
public static String readUTF(DataInputStream in) throws Exception {
int length = in.readInt();
byte[] bytes = new byte[length];
int totalBytesRec = 0;
int bytesRec = 4;
StringBuilder builder = new StringBuilder();
do {
bytesRec = in.read(bytes);
totalBytesRec = bytesRec;
builder.append(new String(bytes, 0, bytesRec, StandardCharsets.UTF_8));
} while (totalBytesRec < length && bytesRec > 0);
return builder.toString();
}
CodePudding user response:
You need to change your ReadUTF
method on server
async Task<string> ReadUTF()
{
byte[] buf = new byte[4];
int totalBytesRec = 0;
do
{
byte[] tmp= new byte[1];
int bytesRec = await socketClient.ReceiveAsync(tmp, SocketFlags.None);
if(bytesRec>0){
buff[totalBytesRec ]=tmp[0];
}
} while (4 == totalBytesRec);
totalBytesRec = 0;
StringBuilder builder = new StringBuilder();
int len = ReverseInt(buf);
buf = new byte[len];
do
{
bytesRec = await socketClient.ReceiveAsync(buf, SocketFlags.None);
totalBytesRec = bytesRec;
builder.Append(Encoding.UTF8.GetString(buf, 0, bytesRec));
} while (totalBytesRec < len && bytesRec > 0);
string result = builder.ToString();
Console.WriteLine($"[ ] Read : {result}");
return result;
}