c# Use tcp socket Send message to Android:
string data = "my message....";
byte[] msg = Encoding.UTF8.GetBytes(data);
//for example msg Length is 5210 bytes
client.socket.SendBufferSize = 500000;
socket.Send(msg, msg.Length, SocketFlags.None);
Android receive message from c# server-side:
socket = new Socket(ServerIP, ServerPort);
socket.setReceiveBufferSize(500000);
isReceive = true;
receiveThread = new ReceiveThread(socket);
receiveThread.start();
private class ReceiveThread extends Thread{
private InputStream inStream = null;
ReceiveThread(Socket socket){
inStream = socket.getInputStream();
}
#Override
public void run(){
while(isReceive){
byte[] buffer = new byte[99999];
try {
//only receive 2896 bytes?
int size = inStream.read(buffer);
} catch (IOException e) {
unConnSocket();
}
}
}
}
why the size only receive 2896 bytes?
Your Android code has no way of knowing how many bytes the C# code is sending. inStream.read() is reading only the bytes that are currently available on the socket at that moment. You should have the C# code send the string length before sending the string data, so that the Android code knows how many bytes to expect, eg:
string data = "my message....";
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
int dataLen = IPAddress.HostToNetworkOrder(dataBytes.Length);
byte[] dataLenBytes = BitConverter.GetBytes(dataLen);
socket.Send(dataLenBytes);
socket.Send(dataBytes);
private class ReceiveThread extends Thread
{
private DataInputStream inStream = null;
ReceiveThread(Socket socket)
{
inStream = new DataInputStream(socket.getInputStream());
}
#Override
public void run()
{
while (isReceive)
{
try
{
String s;
int size = inStream.readInt();
if (size > 0)
{
byte[] buffer = new byte[size];
inStream.readFully(buffer);
s = new String(buffer, "UTF-8");
}
else
s = "";
// use s as needed ...
}
catch (IOException e)
{
unConnSocket();
}
}
}
}
Because TCP is a byte stream protocol and isn't obliged to deliver you more than one byte at a time.
You have to loop.
I quote from Linux man recv(2):
The receive calls normally return any data available, up to the requested amount, rather than waiting for receipt of the full amount requested.
Related
I created socket programming class for client. Connection was made. Server send a message to client. Client can take messages from server. But client only an answer sends. Why? Is the outputstream wrong?
public class Message extends AsyncTask<byte[], Void, Void> {
Socket s;
public static byte[] recv;
#Override
protected Void doInBackground(byte[]... voids) {
byte[] message = voids[0];
try {
s = new Socket(destIp, destPort);
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
dos.writeInt(message.length);
dos.write(message);
dos.flush();
InputStream inFromServer = s.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
byte[] buffer = new byte[200];
int read = 0;
while ((read = in.read(buffer, 0, buffer.length)) != -1) {
// in.read(buffer);
recv = Arrays.copyOf(buffer, read);
Context context = getContext();
Intent intentManager = new Intent(context, ManagerService.class);
context.startService(intentManager);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
I fixed this in the part I start asynctask
new MessageReceive().execute(sendData);
to
new MessageReceive().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,sendData);
I'm playing around ServerSocket on Android as the server part. I don't understand how it behaves. Here are what I tested :
A1. Instantiates a ServerSocket on Android
A2. ServerSocket sends "hello" to client
A3. Client can read the "hello" and can answer back to ServerSocket
A4. ServerSocket on Android receives the answer from the client
=> That works perfectly
Now I want the client to be the first to send a message to ServerSocket :
B1. Instantiates a ServerSocket on Android
B2. Client sends data to ServerSocket
B3. ServerSocket receives the data from client
B4. IMPOSSIBLE TO REPLY to the client
May that be a possible normal behaviour ?
Thanks
here is the source code
public void startServer()
{
log("startServer");
UUID uuid = UUID.randomUUID();
final String sessionId = uuid.toString().replace("-", "");
log("Session ID = " + sessionId);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while (stopServer == false) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(7777);
final Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
String strFromClient = "";
int i = 0;
while (i != -1) {
try {
i = inputStream.read();
if (i != -1)
strFromClient += (char) i;
}catch (Exception e){
break;
}
}
inputStream.close();
OutputStream outputStream = socket.getOutputStream();
String strToClient = "test";
byte[] cArray = strToClient.getBytes();
outputStream.write(cArray);
outputStream.flush();
outputStream.close();
socket.close();
serverSocket.close();
log("end server");
} catch (Exception e) {
//log(e.toString());
}
}
}
});
t.start();
}
Ok I found the solution ! The error was because the C# client was not sending the "-1" value (this is only triggered after closing a stream or stuff like that).
The solution is on the Android side, and the reading of the data from the client is now done as follow :
InputStream inputStream = socket.getInputStream();
String strFromClient = "";
int available = inputStream.available();
Log.d("intelsms", "available from client:" + available);
for (int i=0;i<available;i++){
int c = inputStream.read();
strFromClient+=(char)c;
}
I use the "available()" method in order to know how many bytes are available for reading from the client.
OUF !
How can I output and read strings over a bluetooth socket. Right now it prints the value of the bytes being sent which is the number of character 0-255. So 'hi' would be 2, 'bye' would be 3. Here is my read and write functions:
public void read() {
byte buffer[] = new byte[1024];
final int bytes;
try {
bytes = iStream.read(buffer);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
updateTView(bytes);
}
});
Log.i("WTF",String.valueOf(bytes));
} catch(IOException e) {
//TODO: something
}
}
public void writeText(byte bytes[]) {
try {
oStream.write(bytes);
} catch(IOException e) {
//TODO: something
}
}
private InputStream input;
Perform this in background thread.
byte[] buffer = new byte[1024];
bytes = input.read(buffer);
String readMessage = new String(buffer, 0, bytes);
// Send the obtained bytes to the UI Activity
System.out.println(readMessage);
I am a beginner in developing the java applications. I'm making a chat application on android. I use a thread to serve the client who comes in, but when the client has connected to the server I can not retrieve the data contained in the socket, but when a client connection is lost, data can be displayed. I use the ReadLine method to read data from the socket.
This is the program code on the server side:
package server;
import java.net.*;
import java.io.*;
import java.util.Vector;
import com.sun.org.apache.bcel.internal.generic.NEW;
public class Server {
public static void main(String[] args)throws IOException, InstantiationException,
IllegalAccessException {
ServerSocket servsocket = null;
Socket sock = null;
byte[] bytebuffer = new byte[512];
try {
System.out.println("SERVER IS RUNNING...");
servsocket = new ServerSocket(28000);
while(true){
sock = servsocket.accept();
System.out.println(servsocket.isBound());
System.out.println("Port "+servsocket+" Ready!!!");
System.out.println("Accept connection requests from " + sock);
System.out.println("From CLIENT "+sock.getInetAddress()+ " and PORT " +
sock.getPort());
ChatThread thread = new ChatThread(sock);
System.out.println("Thread is running");
thread.run();
}
} catch (IOException ioe) {
System.out.println(ioe);
}
finally{
try {
servsocket.close();
} catch (IOException ioe) {
System.out.println(ioe);
}
}
}
}
class ChatThread extends Thread{
static Vector<ChatThread> chatthread = new Vector<ChatThread>(10);
private Socket sock;
private BufferedReader in ;
private PrintWriter out;
public ChatThread (Socket socket) throws IOException {
this.sock = socket;
in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream()));
byte[] bytebuffer = new byte[512];
int receivemssg;
}
public void run(){
int recvMsgSize;
byte[] bytebuffer = new byte[512];
String readsocket;
try {
readsocket = in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Below the display on the server side when the program starts. I tried to send the word "Hello ...." from the client side. Can be seen that the thread is not running.
Server is running...
true
Port ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=28000] Ready!!!
Accept connection requests fromSocket[addr=/172.17.231.254,port=3567,localport=28000]
From CLIENT /172.17.231.254 and PORT 3567
Thread is Running...
When I replace the readline method on a thread with getInputStream the thread can be run from the client and the message can be displayed. This is the code that I enter the thread to replace the readline method that I used before.
public ChatThread (Socket socket) throws IOException {
this.sock = socket;
in = sock.getInputStream();
out = sock.getOutputStream();
byte[] bytebuffer = new byte[512];
int receivemssg;
}
public void run(){
int recvMsgSize;
byte[] bytebuffer = new byte[512];
System.out.println("Thread is Running...");
String masuk = new String(bytebuffer);
System.out.println(bytebuffer);
System.out.println(in.toString());
System.out.println("thread successfully executed !!!");
synchronized (chatthread) {
chatthread.addElement(this);
}
try {
while ((recvMsgSize = in.read(bytebuffer)) != -1) {
out.write(bytebuffer, 0, recvMsgSize);
System.out.println("The length of a character is received and returned "+bytebuffer.length);
}
} catch (IOException e) {
System.out.println(e);
}
}
}
but the next problem is I can not bring up the contents of a socket in a string / text that appears is as follows:
Port ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=28000] Siap!!!
Accept connection requests fromSocket[addr=/172.17.231.254,port=3577,localport=28000]
From CLIENT /172.17.231.254 and PORT 3577
Thread is Running...
[B#7c6768
java.net.SocketInputStream#1690726
thread successfully executed !!!
The length of a character is received and returned 512
Please Help me, thanks :) GBU guys...
See the developer docmentation
public final String readLine ()
Since: API Level 1
Returns a string containing the next line of text available from this stream.
A line is made of zero or more characters followed by '\n', '\r', "\r\n"
or the end of the stream. The string does not include the newline sequence.
readLine() will block and not return until it either sees an end-of-line condition such as a newline character, or the end of the stream is reached, which is probably what happens when the connection is lost.
If you want to use readLine() you need to send "Hello....\n" or otherwise append a terminating character for readLine() to see.
I have a client in Android and server in C#, they communicate through socket.
I have this problem - if I run my client app in debug mode and place a breakpoint in right place - it works perfectly, but without it it doesn't.
Client sends adress of an image to server, server makes a thumbnail of it, converts it to byte[] and sends it back. Client gets the byte[], converts it back into image and shows it.
I've also found out that when it doesn't get the right byte[] its size is 2896 and sometimes 1448, no matter what the original size of the array sent was.
Here's the client:
private void connectSocket(String a){
try {
InetAddress serverAddr = InetAddress.getByName("192.168.1.2");
Socket socket = new Socket(serverAddr, 4444);
String message = a;
flag = 0;
if(a.indexOf(".jpg")>0){
flag = 1;
}
ListItems.clear();
if(!a.equalsIgnoreCase("get_drives"))){
//.....
}
if(!ListItems.isEmpty()){
if(ListItems.get(0).matches("^[A-Z]{1}:$")){
ListItems.set(0, ListItems.get(0)+"\\");
}
}
PrintWriter out = null;
BufferedReader in = null;
InputStream is = null;
try {
out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
is = socket.getInputStream();
out.println(message);
String text = "";
String finalText = "";
if(flag!=1){
while ((text = in.readLine()) != null) {
finalText += URLDecoder.decode(text, "UTF-8");
}
String[] result = finalText.split("#");
for(int i = 0; i<result.length; i++)
ListItems.add(result[i]);
}
if(flag ==1){
byte[] buffer = new byte[9999];
//placing breakpoint at the next line or before it makes it work fine
int size = is.read(buffer);
//but placing a breakpoint at the line below doesn't make it work
//it starts getting another byte array
byte[] bufffer2 = new byte[size];
for(int g = 0; g<size;g++){
bufffer2[g] = buffer[g];
}
//is.read(bufffer2);
//int read = is.read(buffer);
image = (ImageView)findViewById(R.id.imageView1);
//while ((text = in.readLine()) != null) {
// byte[] b = in.readLine().getBytes();
Bitmap bmp=BitmapFactory.decodeByteArray(bufffer2,0,bufffer2.length);
image.setImageBitmap(bmp);
//}
}
adapter.notifyDataSetChanged();
} catch(Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
socket.close();
}
} catch (UnknownHostException e) {
Log.e("TCP", "C: UnknownHostException", e);
e.printStackTrace();
} catch (IOException e) {
Log.e("TCP", "C: IOException", e);
e.printStackTrace();
}
}
Here's the server:
public class serv {
public static void Main() {
try {
IPAddress ipAd = IPAddress.Parse("192.168.1.2");
TcpListener myList=new TcpListener(ipAd,4444);
m:
myList.Start();
Socket s=myList.AcceptSocket();
byte[] b=new byte[100];
int k=s.Receive(b);
char cc = ' ';
string test = null;
Console.WriteLine("Recieved...");
for (int i = 0; i < k-1; i++)
{
Console.Write(Convert.ToChar(b[i]));
cc = Convert.ToChar(b[i]);
test += cc.ToString();
}
string[] response = null;
ASCIIEncoding asen = new ASCIIEncoding();
switch (test)
{
default:
MyExplorer(test, s);
break;
}
s.Close();
myList.Stop();
goto m;
}
catch (Exception e) {
Console.WriteLine("Error..... " + e.StackTrace);
}
}
public static void MyExplorer(string r, Socket s){
Image imgThumb = null;
if (r.Contains(".jpg"))
{
Image image = null;
image = Image.FromFile(r);
// Check if image exists
if (image != null)
{
imgThumb = image.GetThumbnailImage(100, 100, null, new IntPtr());
s.Send(imageToByteArray(imgThumb));
byte[] b = imageToByteArray(imgThumb);
}
return;
}
}
public static byte[] imageToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
}
The read(byte []) method in InputStream reads as many bytes as currently available. It does not necessarily mean that there won't be more bytes available later. So you need to do something like
while(true) {
int s = is.read(buffer);
if(s == -1) break;
// else
add read buffer to image array
}
extract image from image array
where "image array" is some byte array where you keep adding the read buffer until you reach then end of the stream.
The reason your code works with the breakpoint is that by the time you go through the debugger the whole stream is available, while in non-debug the whole stream is not yet available when you do the read.
The difference is likely due to the fact that on the debugger, you are able to slow and stop the application - this gives time for the server to respond to your call. It looks like you are not using any asynchronous methods to call connect socket (well, I can't see any evidence of this from your code anyway).
To fix this, you should try extending the AsyncTask object examples here
EDIT: #Carsten probably has the correct solution, but you should STILL use an AsyncTask if you are not already.