Ruby客户端无法从C服务器读取:socket.get挂起
我有一个C语言的服务器和一个Ruby语言的客户端。我的ruby客户机能够成功地将字符串发送到我的C服务器,但它无法接收来自它的任何输入 更具体地说,client.rb中我的“recv”方法中的“get”方法挂起。启动my client.rb程序如下所示:Ruby客户端无法从C服务器读取:socket.get挂起,c,ruby,sockets,networking,client-server,C,Ruby,Sockets,Networking,Client Server,我有一个C语言的服务器和一个Ruby语言的客户端。我的ruby客户机能够成功地将字符串发送到我的C服务器,但它无法接收来自它的任何输入 更具体地说,client.rb中我的“recv”方法中的“get”方法挂起。启动my client.rb程序如下所示: [user]$ ruby client.rb ## CLIENT STARTED ## user: myuser //user enters username and password here password: mypass
[user]$ ruby client.rb
## CLIENT STARTED ##
user: myuser //user enters username and password here
password: mypass // It hangs after this line, so I press ctrl-C
^Cclient.rb:27:in `gets': Interrupt //This is the output after pressing ctrl-C
from client.rb:27:in `verifyUser'
from client.rb:40:in `main'
from client.rb:48
而我的服务器的输出将是:
## SERVER STARTED ##
[Wed Aug 13 12:19:43 2014] 21 bytes 0 myuser mypass
write succeed
request processed
根据我的输出,向客户端写入成功。但是我的ruby客户端在recv方法中调用socket.get时挂起。我也尝试过使用socket.read,但它也挂起了。我只需要从我的服务器获取第一个字节或一行输入
为什么我的客户端不能从服务器接收输入
应该发生的事情清单如下:
- 服务器启动
- 客户端启动,用户输入用户名和密码
- 服务器接收用户名和密码
- 服务器向客户端发送字符串
- 客户端从服务器接收字符串
- 客户端根据字符串执行一些操作
$ip = '127.0.0.1'
$port = 29008
def send(msg)
socket = TCPSocket.new($ip, $port)
socket.write(msg)
socket.close
end
def recv
socket = TCPSocket.new($ip, $port)
data = socket.gets
socket.close
data
end
def verifyUser(user, pw)
send("0 #{user.chomp!} #{pw.chomp!}")
recv =~ /^0/
end
def main
puts "## CLIENT STARTED ##"
print "user: "
user = gets
print "password: "
pw = gets
if verifyUser(user, pw) then
puts "user verified"
else
puts "wrong user or password"
end
end
main
server.c
/* PROCESS REQUEST */
void processRequest(char *input, int cfd) {
int option = 0;
char *ch = "0";
if (option == 0) {
if (send(cfd, ch, strlen(ch), 0) < 0) {
puts ("write error");
} else {
puts ("write succeed");
}
} else {
puts("option is not valid");
}
}
int main() {
int sfd, cfd;
int optval = 1;
char buffer[2000];
char input[2000];
int len;
int idx = 0;
time_t currTime;
char *time_str;
struct sockaddr_in saddr, caddr;
sfd = socket(AF_INET, SOCK_STREAM, 0);
saddr.sin_family = AF_INET; /* Set address family to IPv4 Internet */
saddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any internet address */
saddr.sin_port = htons(29008); /* Set server port to 29008 */
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
bind(sfd, (struct sockaddr *)&saddr, sizeof(saddr));
listen(sfd, 1);
printf("## SERVER STARTED ##\n");
while (1) {
if ((cfd = accept(sfd, (struct sockaddr *)NULL, NULL)) < 0) {
puts("client connection failed");
}
/* get time of message */
currTime = time(NULL);
time_str = asctime(localtime(&currTime));
time_str[strlen(time_str) - 1] = '\0';
/* ensure that all everything is received from client */
while ((len = recv(cfd, buffer, 2000, 0)) > 0) {
buffer[len] = '\0';
if (idx == 0) {
strcpy(input, buffer);
} else {
strcat(input, buffer);
}
/* log message */
printf ("[%s] %d bytes %s\n", time_str, len, input);
idx++;
}
if (len < 0) {
printf("recieve failed\n");
return 1;
}
processRequest(input,cfd);
puts("request processed");
close(cfd);
idx = 0;
input[0] = '\0';
}
return 0;
}
/*处理请求*/
无效处理请求(字符*输入,整数cfd){
int选项=0;
char*ch=“0”;
如果(选项==0){
如果(发送(cfd,ch,strlen(ch),0)<0){
puts(“写入错误”);
}否则{
卖出(“写入成功”);
}
}否则{
看跌期权(“期权无效”);
}
}
int main(){
国际财经事务及库务局;
int optval=1;
字符缓冲区[2000];
字符输入[2000];
内伦;
int-idx=0;
时不我待;
字符*时间长度;
caddr saddr中的结构sockaddr_;
sfd=套接字(AF_INET,SOCK_STREAM,0);
saddr.sin_family=AF_INET;/*将地址系列设置为IPv4 Internet*/
saddr.sin_addr.s_addr=htonl(INADDR_ANY);/*任何互联网地址*/
saddr.sin_port=htons(29008);/*将服务器端口设置为29008*/
setsockopt(sfd、SOL_插座、SO_REUSEADDR和optval、optval尺寸);
绑定(sfd,(struct sockaddr*)和saddr,sizeof(saddr));
聆听(sfd,1);
printf(“###服务器已启动##\n”);
而(1){
如果((cfd=accept(sfd,(struct sockaddr*)NULL,NULL))<0){
puts(“客户端连接失败”);
}
/*获取消息的时间*/
currTime=时间(空);
time_str=asctime(localtime(&currTime));
时间序列[strlen(time-str)-1]='\0';
/*确保从客户处收到所有信息*/
而((len=recv(cfd,buffer,2000,0))>0){
缓冲区[len]='\0';
如果(idx==0){
strcpy(输入、缓冲);
}否则{
strcat(输入、缓冲);
}
/*日志消息*/
printf(“[%s]%d字节%s\n”,时间长度,输入);
idx++;
}
if(len<0){
printf(“接收失败\n”);
返回1;
}
processRequest(输入,cfd);
出售(“已处理请求”);
关闭(cfd);
idx=0;
输入[0]='\0';
}
返回0;
}
编辑
- 我已经修改了我的server.c代码,以反映我现在的情况。我将send方法中的strlen(输入)参数更改为strlen(ch)。问题仍然存在
- 我已经通过telnet测试了我的服务器,结果是一样的。我可以向服务器写入数据,但不能从服务器读取数据。这让我相信我的Ruby客户端没有任何问题。这一定是我的服务器发送数据的方式有问题
def send(s, msg)
print("sending: '" + msg + "'\n")
s.write(msg)
s.flush
end
def recv(s)
print("in recv");
data = s.recv(1024)
print("got data: " + data);
data
end
def verifyUser(user, pw)
socket = TCPSocket.new($ip, $port)
send(socket,"0 #{user.chomp!} #{pw.chomp!}\0")
resp = recv(socket)
socket.close
resp =~ /^0/
end
2) 在c服务器中-len=recv while循环-您真的需要while循环吗?服务器再次读取命令和循环。它以前工作的唯一原因是,您关闭了套接字,然后recv出现错误,跳出循环并处理了请求。如果将processRequest放在带有时间戳的printf下面,您将看到服务器确实发送了响应。如果你整理一下ruby客户端的套接字,你会得到相应的响应
def send(socket, msg)
socket.puts(msg) # puts() adds a newline for the server.
socket.flush # Probably not necessary.
end
def recv(socket)
# gets() doesn't end until receives a newline.
socket.gets
end
def verifyUser(user, pw)
response = ''
# Use 1 socket for both send/recv.
# Can use open() with a block to auto-close
# at the end of the block.
TCPSocket.open($ip, $port) do |socket|
send(socket,"0 #{user.chomp!} #{pw.chomp!}")
response = recv(socket)
end
response =~ /^0/
end
C代码:
void processRequest(char *input, int cfd) {
int option = 0;
char *ch = "0\n"; // Newline!
//...
}
//...
/* ensure that all everything is received from client */
while ((len = recv(cfd, buffer, 2000, 0)) > 0) {
buffer[len] = '\0';
if (idx == 0) {
strcpy(input, buffer);
} else {
strcat(input, buffer);
}
/* log message */
printf ("[%s] %d bytes %s\n", time_str, len, input);
idx++;
// Note that this is just a simple version.
// You probably want to store a substring into input.
// Then save the rest of the substring in the buffer.
// Include "stdbool.h" if don't want to use an int.
int has_newline = 0;
for(int i = 0; i < len; ++i) {
if(buffer[i] == '\n') {
printf("Breaking out of loop.\n");
has_newline = 1;
break;
}
}
if(has_newline == 1) {
break;
}
}
//...
void processRequest(字符*输入,int cfd){
int选项=0;
char*ch=“0\n”;//换行符!
//...
}
//...
/*确保从客户处收到所有信息*/
而((len=recv(cfd,buffer,2000,0))>0){
缓冲区[len]='\0';
如果(idx==0){
strcpy(输入、缓冲);
}否则{
strcat(输入、缓冲);
}
/*日志消息*/
printf(“[%s]%d字节%s\n”,时间长度,输入);
idx++;
//请注意,这只是一个简单的版本。
//您可能希望将子字符串存储到输入中。
//然后将子字符串的其余部分保存在缓冲区中。
//如果不想使用int,请包括“stdbool.h”。
int具有_新行=0;
对于(int i=0;i
很抱歉,我编辑了processRequest meth