服务端如何像客户端发送消息(使用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 )????跪求各位大侠^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
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 )????跪求各位大侠^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UP UP UP
2——客户端发数据给服务端,服务端得到的端口一定不是固定的!因为假设A客户端和B客户端在一个局域网里,那么在公网上A 和B的IP是一样的,只是端口不一样!这个就上著名的公网像内网发数据不是一个简单的事情!
3——所以让 服务器端和客户端彼此约定一个固定的端口几乎不太可能!(个人意见!)即使能也是短暂的所以问题仍然存在
1。中转服务器
2。参考P2P吧
如果是中转服务器,比较简单
如果是P2P 的话,在SERVER端用IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0)来接受CLIENT端的外网IP和PORT,如果NAT穿透成功的话,直接S->C,C是可以接受到S的信息的,如果接受不到,那得继续NAT穿透
//=====================开始=========================================================如果使用服务器中转!
问题是服务器如何和客户端联系!
情况是这样的,服务器是可以得到客户端的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
的却存在当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);
说白了,现在也用不着服务器中转了
使用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有两台机子时你就要想点法子了。也比较容易。
绝对没问题。
如果你保证你的代码没问题的话,说不定是你的NAPT是Symmetric 类型的,如果真是这样的类型的话,你不妨在服务器端接受到最新的客护端口(例如 9000)上再加 1 (即 9001)试试看,也就是P2P中的猜测端口方法了
不过大部分的NAPT是CONE类型的