我正在使用5个字符串(协议,源IP和端口,目标IP和端口)并使用它们在散列中存储一些值。问题是如果IP或端口在源和目的地之间切换,则密钥应该是相同的。
如果我在C#/ Java /中做这件事,无论我需要创建一个新类并覆盖hashcode()/ equals()方法,但这似乎很容易从我读过的关于它和我想知道这里是否会有更好的选择。
答案 0 :(得分:4)
我正在直接复制 Programming Ruby 1.9 :
中的段落哈希键必须通过返回哈希码来响应消息
hash
,并且给定键的哈希码不得更改。哈希中使用的键也必须使用eql?
进行比较。如果eql?
为两个键返回true
,那么这些键也必须具有相同的哈希码。这意味着某些类(例如Array
和Hash
)不能方便地用作键,因为它们的哈希值可能会根据其内容而改变。
因此,您可能会生成类似["#{source_ip} #{source_port}", "#{dest_ip} #{dest_port}", protocol.to_s].sort.join.hash
的哈希值,以便在切换源和目标时结果相同。
例如:
source_ip = "1.2.3.4"
source_port = 1234
dest_ip = "5.6.7.8"
dest_port = 5678
protocol = "http"
def make_hash(s_ip, s_port, d_ip, d_port, proto)
["#{s_ip} #{s_port}", "#{d_ip} #{d_port}", proto.to_s].sort.join.hash
end
puts make_hash(source_ip, source_port, dest_ip, dest_port, protocol)
puts make_hash(dest_ip, dest_port, source_ip, source_port, protocol)
即使两个调用之间的参数顺序不同,也会输出相同的哈希值。将此功能正确地封装到一个类中是留给读者的练习。
答案 1 :(得分:0)
我认为这就是你的意思......
irb(main):001:0> traffic = []
=> []
irb(main):002:0> traffic << {:src_ip => "10.0.0.1", :src_port => "9999", :dst_ip => "172.16.1.1", :dst_port => 80, :protocol => "tcp"}
=> [{:protocol=>"tcp", :src_ip=>"10.0.0.1", :src_port=>"9999", :dst_ip=>"172.16.1.1", :dst_port=>80}]
irb(main):003:0> traffic << {:src_ip => "10.0.0.2", :src_port => "9999", :dst_ip => "172.16.1.1", :dst_port => 80, :protocol => "tcp"}
=> [{:protocol=>"tcp", :src_ip=>"10.0.0.1", :src_port=>"9999", :dst_ip=>"172.16.1.1", :dst_port=>80}, {:protocol=>"tcp", :src_ip=>"10.0.0.2", :src_port=>"9999", :dst_ip=>"172.16.1.1", :dst_port=>80}]
下一个有点相关的问题是如何存储IP。您可能希望使用IPAddr对象而不仅仅是字符串,以便您可以更轻松地对结果进行排序。
答案 2 :(得分:0)
您可以使用以下代码:
def create_hash(prot, s_ip, s_port, d_ip, d_port, value, x = nil)
if x
x[prot] = {s_ip => {s_port => {d_ip => {d_port => value}}}}
else
{prot => {s_ip => {s_port => {d_ip => {d_port => value}}}}}
end
end
# Create a value
h = create_hash('www', '1.2.4.5', '4322', '4.5.6.7', '80', "Some WWW value")
# Add another value
create_hash('https', '1.2.4.5', '4562', '4.5.6.7', '443', "Some HTTPS value", h)
# Retrieve the values
puts h['www']['1.2.4.5']['4322']['4.5.6.7']['80']
puts h['https']['1.2.4.5']['4562']['4.5.6.7']['443']