我必须为 java 程序使用套接字编程与 TCL 程序通信的场景编写程序。 我分别成功地尝试了TCL 和Java 的套接字编程。但是由于我必须有一个 Java 程序作为客户端套接字和 TCL 程序作为服务器,所以我无法成功完成。
服务器的TCL程序
set svcPort 9999
#Implement the service
# This example just writes the info back to the client...
proc doService {sock msg} {
puts $sock "$msg"
}
# Handles the input from the client and client shutdown
proc svcHandler {sock} {
set l [gets $sock] ;# get the client packet
puts "The packet from the client is $l"
if {[eof $sock]} { ;# client gone or finished
close $sock ;# release the servers client channel
} else {
doService $sock $l
}
}
# Accept-Connection handler for Server.
# called When client makes a connection to the server
# Its passed the channel we're to communicate with the client on,
# The address of the client and the port we're using
#
# Setup a handler for (incoming) communication on
# the client channel - send connection Reply and log connection
proc accept {sock addr port} {
# if {[badConnect $addr]} {
# close $sock
# return
# }
# Setup handler for future communication on client socket
fileevent $sock readable [list svcHandler $sock]
# Read client input in lines, disable blocking I/O
fconfigure $sock -buffering line -blocking 0
# Send Acceptance string to client
puts $sock "$addr:$port, You are connected to the echo server."
puts $sock "It is now [exec date]"
# log the connection
puts "Accepted connection from $addr at [exec date]"
}
# Create a server socket on port $svcPort.
# Call proc accept when a client attempts a connection.
socket -server accept $svcPort
vwait events ;# handle events till variable events is set
和
Java客户端程序
// File Name GreetingClient.java
import java.net.*;
import java.io.*;
public class GreetingClient
{
public static void main(String [] args)
{
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try
{
System.out.println("Connecting to " + serverName
+ " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to "
+ client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out =
new DataOutputStream(outToServer);
out.writeUTF("Hello from "
+ client.getLocalSocketAddress()+"\n");
InputStream inFromServer = client.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
我启动了服务器,服务器什么也没显示。
我启动了客户端,服务器显示“Accepted connection from at Mon May 6 02:50:21 PDT 2013”并且客户端显示 “连接到端口 9999 刚刚连接到/(服务器 ip 地址):9999"
当 out.writeUTF 在客户端执行时,服务器显示“来自客户端的数据包是
"Hello from : /<client ip address>:<client port no>".
但客户端没有显示任何内容,因为它应该显示来自服务器的回复。客户端进程确实不退出并等待System.out.println("Server says " + in.readUTF());
的执行。
有人可以在这里帮忙并告诉为什么当连接存在时客户端无法看到服务器的回复,而客户端可以向服务器发送数据。
谢谢
最佳答案
您的 Java 客户端正在使用 DataOutputStream.writeUTF
和 DataInputStream.readUTF
;这些在套接字之上使用简单的成帧协议(protocol),Tcl 服务器不使用它。这会使事情出错。
框架协议(protocol)非常简单。首先,字符串的长度(以字节为单位)被写成一个双字节大端(“网络端”)整数。然后发送字符串的 UTF-8 字节。非常简单,但您需要知道才能真正正确地处理它。以这种方式工作时,您还希望将套接字置于二进制模式;您不再使用面向线路的协议(protocol)。
# Two helper procedures that know how to do the framing encoding/decoding
proc writeJavaUTF {sock msg} {
set data [encoding convertto utf-8 $msg]
puts -nonewline $sock [binary format "S" [string length $data]]$data
}
proc readJavaUTF {sock} {
binary scan [read $sock 2] "S" len
set data [read $sock [expr {$len & 0xFFFF}]]
return [encoding convertfrom utf-8 $data]
}
# This is your sample code, stripped of comments and adapted
set svcPort 9999
proc doService {sock msg} {
writeJavaUTF $sock "$msg"; # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
proc svcHandler {sock} {
set l [readJavaUTF $sock]; # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
puts "The packet from the client is $l"
if {[eof $sock]} {
close $sock
} else {
doService $sock $l
}
}
proc accept {sock addr port} {
fileevent $sock readable [list svcHandler $sock]
# Next *three* lines are changed!
fconfigure $sock -buffering line -blocking 0 -translation binary
writeJavaUTF $sock "$addr:$port, You are connected to the echo server."
writeJavaUTF $sock "It is now [exec date]"
puts "Accepted connection from $addr at [exec date]"
}
socket -server accept $svcPort
vwait events
关于java - Java和TCL之间的套接字编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16396660/