iPhone客户端与Java服务器对话
我试着让iphone客户端与Java服务器对话,这是Java服务器代码:iPhone客户端与Java服务器对话,java,iphone,objective-c,client-server,Java,Iphone,Objective C,Client Server,我试着让iphone客户端与Java服务器对话,这是Java服务器代码: import java.io.*; import java.net.*; import java.text.SimpleDateFormat; import java.util.*; public class Server { // a unique ID for each connection private static int uniqueId; // an ArrayList to keep the list o
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class Server {
// a unique ID for each connection
private static int uniqueId;
// an ArrayList to keep the list of the Client
private ArrayList<ClientThread> al;
// if I am in a GUI
private ServerGUI sg;
// to display time
private SimpleDateFormat sdf;
// the port number to listen for connection
private int port;
// the boolean that will be turned of to stop the server
private boolean keepGoing;
/*
* server constructor that receive the port to listen to for connection as parameter
* in console
*/
public Server(int port) {
this(port, null);
}
public Server(int port, ServerGUI sg) {
// GUI or not
this.sg = sg;
// the port
this.port = port;
// to display hh:mm:ss
sdf = new SimpleDateFormat("HH:mm:ss");
// ArrayList for the Client list
al = new ArrayList<ClientThread>();
}
public void start() {
keepGoing = true;
/* create socket server and wait for connection requests */
try
{
// the socket used by the server
ServerSocket serverSocket = new ServerSocket(port);
// infinite loop to wait for connections
while(keepGoing)
{
// format message saying we are waiting
display("Server waiting for Clients on port " + port + ".");
Socket socket = serverSocket.accept(); // accept connection
// if I was asked to stop
if(!keepGoing)
break;
ClientThread t = new ClientThread(socket); // make a thread of it
al.add(t); // save it in the ArrayList
t.start();
}
// I was asked to stop
try {
serverSocket.close();
for(int i = 0; i < al.size(); ++i) {
ClientThread tc = al.get(i);
try {
tc.sInput.close();
tc.sOutput.close();
tc.socket.close();
}
catch(IOException ioE) {
// not much I can do
}
}
}
catch(Exception e) {
display("Exception closing the server and clients: " + e);
}
}
// something went bad
catch (IOException e) {
String msg = sdf.format(new Date()) + " Exception on new ServerSocket: " + e + "\n";
display(msg);
}
}
/*
* For the GUI to stop the server
*/
protected void stop() {
keepGoing = false;
// connect to myself as Client to exit statement
// Socket socket = serverSocket.accept();
try {
new Socket("localhost", port);
}
catch(Exception e) {
// nothing I can really do
}
}
/*
* Display an event (not a message) to the console or the GUI
*/
private void display(String msg) {
String time = sdf.format(new Date()) + " " + msg;
if(sg == null)
System.out.println(time);
else
sg.appendEvent(time + "\n");
}
/*
* to broadcast a message to all Clients
*/
private synchronized void broadcast(String message) {
// add HH:mm:ss and \n to the message
String time = sdf.format(new Date());
String messageLf = time + " " + message + "\n";
// display message on console or GUI
if(sg == null)
System.out.print(messageLf);
else
sg.appendRoom(messageLf); // append in the room window
// we loop in reverse order in case we would have to remove a Client
// because it has disconnected
for(int i = al.size(); --i >= 0;) {
ClientThread ct = al.get(i);
// try to write to the Client if it fails remove it from the list
if(!ct.writeMsg(messageLf)) {
al.remove(i);
display("Disconnected Client " + ct.username + " removed from list.");
}
}
}
// for a client who logoff using the LOGOUT message
synchronized void remove(int id) {
// scan the array list until we found the Id
for(int i = 0; i < al.size(); ++i) {
ClientThread ct = al.get(i);
// found it
if(ct.id == id) {
al.remove(i);
return;
}
}
}
/*
* To run as a console application just open a console window and:
* > java Server
* > java Server portNumber
* If the port number is not specified 1500 is used
*/
public static void main(String[] args) {
// start server on port 1500 unless a PortNumber is specified
int portNumber = 1500;
switch(args.length) {
case 1:
try {
portNumber = Integer.parseInt(args[0]);
}
catch(Exception e) {
System.out.println("Invalid port number.");
System.out.println("Usage is: > java Server [portNumber]");
return;
}
case 0:
break;
default:
System.out.println("Usage is: > java Server [portNumber]");
return;
}
// create a server object and start it
Server server = new Server(portNumber);
server.start();
}
/** One instance of this thread will run for each client */
class ClientThread extends Thread {
// the socket where to listen/talk
Socket socket;
ObjectInputStream sInput;
ObjectOutputStream sOutput;
// my unique id (easier for deconnection)
int id;
// the Username of the Client
String username;
// the date I connect
String date;
// Constructore
ClientThread(Socket socket) {
// a unique id
id = ++uniqueId;
this.socket = socket;
/* Creating both Data Stream */
System.out.println("Thread trying to create Object Input/Output Streams");
try
{
// create output first
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
// read the username
username = (String) sInput.readObject();
display(username + " just connected.");
}
catch (IOException e) {
display("Exception creating new Input/output Streams: " + e);
return;
}
// have to catch ClassNotFoundException
// but I read a String, I am sure it will work
catch (ClassNotFoundException e) {
}
date = new Date().toString() + "\n";
}
// try to close everything
private void close() {
// try to close the connection
try {
if(sOutput != null) sOutput.close();
}
catch(Exception e) {}
try {
if(sInput != null) sInput.close();
}
catch(Exception e) {};
try {
if(socket != null) socket.close();
}
catch (Exception e) {}
}
/*
* Write a String to the Client output stream
*/
private boolean writeMsg(String msg) {
// if Client is still connected send the message to it
if(!socket.isConnected()) {
close();
return false;
}
// write the message to the stream
try {
sOutput.writeObject(msg);
}
// if an error occurs, do not abort just inform the user
catch(IOException e) {
display("Error sending message to " + username);
display(e.toString());
}
return true;
}
}
}
仅使用这行代码,我就可以连接到Java服务器,在服务器中,我在终端中接收到这行代码:
Thread trying to create Object Input/Output Streams
因此,它与服务器连接,然后我尝试通过以下方式发送用户名:
NSString *username = @"user";
NSData *data = [[NSData alloc] initWithData:[username dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
NSData *_data=[username dataUsingEncoding:NSUTF8StringEncoding];
int data_len = [_data length];
uint8_t *readBytes = (uint8_t *)[_data bytes];
int byteIndex=0;
unsigned int len=0;
while (TRUE) {
len = ((data_len - byteIndex >= 40960) ? 40960 : (data_len-byteIndex));
if(len==0)
break;
uint8_t buf[len];
(void)memcpy(buf, readBytes, len);
len = [outputStream write:(const uint8_t *)buf maxLength:len]; byteIndex += len;
readBytes += len;
}
但在服务器终端中,我收到以下信息:
Exception creating new Input/output Streams: java.io.StreamCorruptedException: invalid stream header: 69616D3A
我还尝试以这种方式发送信息:
NSString *username = @"user";
NSData *data = [[NSData alloc] initWithData:[username dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
NSData *_data=[username dataUsingEncoding:NSUTF8StringEncoding];
int data_len = [_data length];
uint8_t *readBytes = (uint8_t *)[_data bytes];
int byteIndex=0;
unsigned int len=0;
while (TRUE) {
len = ((data_len - byteIndex >= 40960) ? 40960 : (data_len-byteIndex));
if(len==0)
break;
uint8_t buf[len];
(void)memcpy(buf, readBytes, len);
len = [outputStream write:(const uint8_t *)buf maxLength:len]; byteIndex += len;
readBytes += len;
}
<> P>但也以同样的方式接收到相同的异常,如何发送消息到java服务器?< /p> 没有具体的帮助,但是考虑使用AfNETS。(在github上) 网络总是很难建立,而且这个框架非常棒 啊..您试图在java端写入对象流。。它们使用专有的字节格式。您没有以预期的方式发送数据(错误的字节=>没有java对象)
<>我真的会使用JSON、XML或一个更简单的“协议”< /P>
,对您的代码没有具体的帮助,但是考虑使用AfNETREST。(在github上) 网络总是很难建立,而且这个框架非常棒
啊..您试图在java端写入对象流。。它们使用专有的字节格式。您没有以预期的方式发送数据(错误的字节=>没有java对象)我真的会选择JSON、xml或更简单的“协议”版本我知道web上有很多框架,但我的目标是在没有任何第三方框架的情况下实现……我认为主要问题是您使用对象{input/output}流与非java套接字进行通信。您应该使用DataInputStream或java提供的其他流来读取原始数据。然后,您可以实现自己的协议,或者在…@filipenf上使用XML、JSON和sos,我就是这么说的;)也许下次我应该大胆点^^^对不起^^坏心情:D没有不愉快的感觉!我知道web上有很多框架,但我的目标是在没有任何第三方框架的情况下实现它……我认为主要问题是您使用对象{input/output}流与非java套接字进行通信。您应该使用DataInputStream或java提供的其他流来读取原始数据。然后,您可以实现自己的协议,或者在…@filipenf上使用XML、JSON和sos,我就是这么说的;)也许下次我应该大胆点^^^对不起^^坏心情:D没有不愉快的感觉!根据“ObjectInputStream反序列化以前使用ObjectOutputStream编写的基本数据和对象”。现在问题似乎很明显,
ObjectOutputStream
包含的头文件允许ObjectInputStream
了解要读取的对象类型。您可能需要弄清楚这些头是什么,然后将它们添加到Obj-C端,或者,我建议您从流中读取原始字节,直到到达\0
。感谢您的回答,但是如果您在问题中看到,我无法确定此头是什么类型,在对象C的第二个示例中,我做了很多编码,但不起作用…如果你能给我一个例子,请…我建议不要弄清楚那些头,那个类是用来在它自己内部通信的(ObjectOutput/ObjectInput)。相反,尝试在Java端使用DataInputStream
和DataOutputStream
。然后使用BufferedReader
读取数据输入流中的行。您已经解决了这个问题还是仍然需要帮助?是的,非常感谢您的兴趣,我已经使用datainputstream和dataoutpustream解决了这个问题!根据“ObjectInputStream反序列化以前使用ObjectOutputStream编写的基本数据和对象”。现在问题似乎很明显,ObjectOutputStream
包含的头文件允许ObjectInputStream
了解要读取的对象类型。您可能需要弄清楚这些头是什么,然后将它们添加到Obj-C端,或者,我建议您从流中读取原始字节,直到到达\0
。感谢您的回答,但是如果您在问题中看到,我无法确定此头是什么类型,在对象C的第二个示例中,我做了很多编码,但不起作用…如果你能给我一个例子,请…我建议不要弄清楚那些头,那个类是用来在它自己内部通信的(ObjectOutput/ObjectInput)。相反,尝试在Java端使用DataInputStream
和DataOutputStream
。然后使用BufferedReader
读取数据输入流中的行。您已经解决了这个问题还是仍然需要帮助?是的,非常感谢您的兴趣,我已经使用datainputstream和dataoutpustream解决了这个问题!