服务端如何像客户端发送消息(使用Socket UDP )????服务端是接收的到客户端的消息,但是服务端如何回应客户端呢?//看看我的代码(服务端)public void sk()//这里是一个线程的执行过程
{
  while(true)
  {
    s= new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);    IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);     //主要在这里,由于这里是服务端(知道固定的IP,和发往固定的端口
    EndPoint localEp=new IPEndPoint(IPAddress.Any,11200);    //所以这里的bind很顺利,因为客户端发过来的端口是11200
    s.Bind(localEp);

    EndPoint senderRemote = (EndPoint)sender;     

    byte[] msg = new byte[2500];
    
    //使用ReceiveFrom必须先使用s.Bind
    s.ReceiveFrom(msg,SocketFlags.None, ref senderRemote);
    
    
    //下面是服务端一个组件(textBox)接收数据
    textBox2.Text+=System.Text.UTF8Encoding.UTF8.GetString(msg)+"\r\n";    //获得了客户端的IP和发送端口(当然这里的客户端端口不会是一个固定的值)
    IPEndPoint sender2=(IPEndPoint)senderRemote;    textBox2.Text+=sender2.Address.ToString()+"\r\n";    textBox2.Text+=sender2.Port.ToString()+"\r\n";    textBox2.Text+="____________________________________\r\n";
    //在这里服务端收到消息后立即回复客户端口
    byte[] ByteGet=new byte[2500];    ByteGet=System.Text.UTF8Encoding.UTF8.GetBytes("服务器已经接收到!!!!!!!!!!!!");
    
    //这里回复给客户端(由于恢复的客户端端口不确定,但是我们可以从senderRemote这里知道)
    s.SendTo(ByteGet,SocketFlags.None,senderRemote);   //最后结束
    s.Close();
   }
}
//=========================================================================
客户端代码
public void sk()//发送过程,不在线程里,使用一个按钮事件调用
{
s= new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp); byte[] ByteGet=new byte[2500];

ByteGet=System.Text.UTF8Encoding.UTF8.GetBytes("发送了数据");

IPAddress a = IPAddress.Parse("219.137.203.209");

receivePoint = new IPEndPoint (a,11200);
            
EndPoint senderRemote = (EndPoint)receivePoint;

//发送给服务端,因为服务端是固定的IP和端口11200
                           //如果这里发送的端口不是11200,那么服务端接收不到
                           //因为在服务端代码里面已经s.Bind(localEp);到了11200
                           s.SendTo(ByteGet,SocketFlags.None,senderRemote);
         s.Close();
                          //结果服务端可以正常接收,多太客户端同时发送,服务端也可以接收
}
客户端接收服务端代码 public void cs()//一个线程的过程
{
while ( true )
{
s1= new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);//设置超过
s1.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout, 
3000
);
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);

                                    //问题就在这里,到底客户端该如何Bind,跪求请高高高高手
EndPoint localEp=new IPEndPoint(IPAddress.Any,11003);

                                     s1.Bind(localEp); EndPoint senderRemote = (EndPoint)sender;

byte[] msg = new byte[2500]; int i=0;
try
{                           //这里怎么样都无法得到服务器返回的消息
                           //我估计原因就在s1.Bind(localEp);但是localEp该如何设置呢?
                           //服务器每次返回端口的都不一样
s1.ReceiveFrom(msg,SocketFlags.None, ref senderRemote);
                           textBox4.Text+=System.Text.UTF8Encoding.UTF8.GetString(msg)+"\r\n";

}
catch(SocketException e)
{
textBox5.Text=e.Message;

} s1.Close(); } }//============================================================================
哎^^^^^^就是这个问题,我查看了大量的文章和大量的论坛,都没有找到答案!!!
也就是服务端如何像客户端发送消息(使用Socket UDP )????跪求各位大侠^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解决方案 »

  1.   

    各位大哥大姐帮帮忙呀^^^^^^^
    UP UP  UP
      

  2.   

    使用Socket UDP,再加上NAT的转发,在加上公网上,那么服务端和客户端无法预订端口哦!1——服务器在公网,那么具有固定IP和端口,这个是可以定下的!
    2——客户端发数据给服务端,服务端得到的端口一定不是固定的!因为假设A客户端和B客户端在一个局域网里,那么在公网上A 和B的IP是一样的,只是端口不一样!这个就上著名的公网像内网发数据不是一个简单的事情!
    3——所以让 服务器端和客户端彼此约定一个固定的端口几乎不太可能!(个人意见!)即使能也是短暂的所以问题仍然存在
      

  3.   

    使用NAT将内网Ip mapping为路由器的端口,假设为KK(此路由器应该在公网,以下所说才成立),服务端所收到的数据报将是你的路由器Ip,假设为IK, 服务器向IK的KK端口发送的数据将由路由器转发给客户端。
      

  4.   

    2种方法:
    1。中转服务器
    2。参考P2P吧
    如果是中转服务器,比较简单
    如果是P2P 的话,在SERVER端用IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0)来接受CLIENT端的外网IP和PORT,如果NAT穿透成功的话,直接S->C,C是可以接受到S的信息的,如果接受不到,那得继续NAT穿透
      

  5.   

    请高人看完本贴,请高人贴出代码,如果测试成功,我将贴上完整的UDP通讯方式(通过服务器中转方式的),UP UP UP UP UP UP UP UP高人请看___________________________________________________________
    //=====================开始=========================================================如果使用服务器中转!
    问题是服务器如何和客户端联系!
    情况是这样的,服务器是可以得到客户端的IP和端口的,但是由于有NAT的转发,所以服务器每次得到的客户端口是不一样的!
    我们假设一种情况:
    客户端:内网IP是192.168.1.100 ,外网IP是219.17.13.209 
    客户端发送服务端:由于服务端的IP是219.137.203.209(固定的),端口为11200
    所以客户端口的发送代码为:
    //===========客户端发送代码===============================================
    s= new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
    byte[] ByteGet=new byte[2500];
    ByteGet=System.Text.UTF8Encoding.UTF8.GetBytes("发送了数据");
    IPAddress a = IPAddress.Parse("219.137.203.209");
    receivePoint = new IPEndPoint (a,11200);            
    EndPoint senderRemote = (EndPoint)receivePoint;
    s.SendTo(ByteGet,SocketFlags.None,senderRemote);
    s.Close();
    //===========客户端发送代码END===============================================
    那么服务端接收代码为:
    //===========服务端接收代码===============================================
    s= new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
    IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
    EndPoint localEp=new IPEndPoint(IPAddress.Any,11200);
    s.Bind(localEp);
    EndPoint senderRemote = (EndPoint)sender;    
    byte[] msg = new byte[2500];
    s.ReceiveFrom(msg,SocketFlags.None, ref senderRemote);//在这里senderRemote包含着客户端的共网IP和端,不过这个端可不是11200了,而是一个随时变换的数据
    //===========服务端接收代码END===============================================那么服务端得到了senderRemote,就可以像客户端发送数据了
    我们可以利用这样的代码来查看客户端的IP和端
    IPEndPoint sender2=(IPEndPoint)senderRemote;
    sender2.Address.ToString();//表示客户端共网IP
    sender2.Port.ToString();//表示客户端发送UDP报文端口(注意是随时可变的)//===========服务端发送代码===============================================
    s= new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
    byte[] ByteGet=new byte[2500];
    ByteGet=System.Text.UTF8Encoding.UTF8.GetBytes("服务器已经接收到!!!!!!!!!!!!");
    s.SendTo(ByteGet,SocketFlags.None,senderRemote);
    //===========服务端发送代码END===============================================
    好了问题出来了!!!!!!!(用的方法是服务器中转,这样服务器已经可以发送数据到客户端了,经过测试也的确是发送了,可是客户端如何接收是个问题了,那位高人可以指点一下,贴出代码来)//===========客户端接收代码===============================================s= new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
    //这样Bind肯定接收不到
    //EndPoint localEp=new IPEndPoint(IPAddress.Any,11200);
    //s.Bind(localEp);//这样Bind肯定接收不到
    //EndPoint localEp=new IPEndPoint(IPAddress.Any,0);
    //s.Bind(localEp);所以客户端这里该如何Bind,请高人指点,或者有没有其他的办法,问题就在这里!!!!!!请高人贴出代码,如果测试成功,我将贴上完整的UDP通讯方式(通过服务器中转方式的)
    IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
    EndPoint senderRemote = (EndPoint)sender;
        
    byte[] msg = new byte[2500];s.ReceiveFrom(msg,SocketFlags.None, ref senderRemote);//===========客户端接收代码END===============================================//=====================结束=========================================================
    请高人看完本贴,请高人贴出代码,如果测试成功,我将贴上完整的UDP通讯方式(通过服务器中转方式的),UP UP UP UP UP UP UP UP
      

  6.   

    由于你的通讯是S->C,C->S的模式,没有C->C,所以涉及不到P2P的NAT穿透
    的却存在当C发消息给S的时候,每次发,IP是相同的,端口一直在变化,而且没规律的,不象P2P中的NAT是对称型的话,他的端口变化还有点规律的,每次加1吧
    虽然端口一直在变化,你只要记下最近一次的端口是多少,然后往这个端口发消息,NAT会自动把此消息包根据映射出来的端口号转发到内网的某台机器
    大体代码:
    在服务端写个这样的 IPEndPoint 对象
    private IPEndPoint remotePoint;
    remotePoint = new IPEndPoint(IPAddress.Any,0);
    byte[] msgBuffer = server.Receive(ref remotePoint);//接受任何SOCKET 对象发来的消息
    IPEndPoint userEndPoint = new IPEndPoint(remotePoint.Address,remotePoint.Port);//记下当前的对象的IP和PORT,可以放在一个列表中存放起来
    public  UdpClient server;
    server = new UdpClient(Port);//Port是先前定义好的端口,且客户端是知道服务器端的IP和PORT的,可以用下面的语句直接给C回发消息,也可以用这个userEndPoint 对象代替下面的remotePoint参数
    server.Send(buffer,buffer.Length,remotePoint);
    说白了,现在也用不着服务器中转了
      

  7.   

    根本用不着中转,你会NAT吧?
    使用NAT将内网Ip mapping为路由器的端口,假设为KK(此路由器应该在公网,以下所说才成立),服务端所收到的数据报将是你的路由器Ip,假设为IK, 服务器向IK的KK端口发送的数据将由路由器转发给客户端。
    例如:
    客户端A,IP=192.168.1.21, 监听在10000
    A所入口IP=70.134.123.123,(路由器的IP),将A mapping 为:
    external Ip       external Port     A               A_port
    70.134.123.123    12000           192.168.1.21      10000
    服务器只向external IP的External port发就行了,不要注意服务器收到的端口回应,当A所在的LAN有两台机子时你就要想点法子了。也比较容易。
    绝对没问题。
      

  8.   

    NAPT 有2中类型,你可以网上查查的
    如果你保证你的代码没问题的话,说不定是你的NAPT是Symmetric 类型的,如果真是这样的类型的话,你不妨在服务器端接受到最新的客护端口(例如 9000)上再加 1 (即 9001)试试看,也就是P2P中的猜测端口方法了
    不过大部分的NAPT是CONE类型的
      

  9.   

    楼主说的这种问题根本不存在客户端不能和服务器通讯的问题,因为服务器始终是在公网上,客户端可以明确服务器的IP和端口,在客户端发送消息到服务器的时候,既使客户端是在内网中也是客户端先发送消息到服务器端,这样客户端就自动在它自己的N AT设备上注册了服务器的IP,这样服务器只要记录客户端的公网IP和端口就行了,因为服务器再发消息到客户端的时候NAT设备会自动把消息转发到在内网中客户端的IP和端口,所以这里根本不存在UDP穿透,因为没有客户端到客户端的通讯,既使存在这种情况,那么只要NAT中间设备不是CONE类型之外的也可以通过穿透的方法进行通讯!