有两种方案:
1、在PC机上建立服务器,手机与手机之间的通信通过服务器进行中转
2、一部手机作为服务器,另一部手机作为客户端接入该手机
一般是第一种方案
示例代码:
1、pc端:serverSocket=new ServerSocket(5648) //在5648端口进行侦听
Socket sk = serverSocket.accept()//如果有接入,则创建对应的socket
2、手机端:
socket=new Socket("tobacco5648.xicp.net",5648)//连接socket
3、消息输入输出:
pw=new PrintWriter(socket.getOutputStream()) //消息输出
pw.println("发送消息")
pw.flush()
br=new BufferedReader(new InputStreamReader(socket.getInputStream())) //消息接收
while((str=br.readLine())!=null){
//接收消息
}
可以,内网之间实现TCP通讯需要用到内网穿透技术。以下是示例代码。
服务端代码:
static void Main(string[] args)
{
int port = 555
IPEndPoint ipe = new IPEndPoint(IPAddress.Any, port)
Socket sSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
sSocket.Bind(ipe)
sSocket.Listen(100)
Console.WriteLine("监听已经打开,请等待")
while (true)
{
Socket serverSocket1 = sSocket.Accept()
Console.WriteLine("连接已经建立")
string recStr = ""
byte[] recByte = new byte[4096]
int bytes = serverSocket1.Receive(recByte)
IPEndPoint ep1 = (IPEndPoint)serverSocket1.RemoteEndPoint
Console.WriteLine(" from {0}", ep1.ToString())
recStr = Encoding.ASCII.GetString(recByte, 0, bytes)
Console.WriteLine("客户端1:{0}", recStr)
Socket serverSocket2 = sSocket.Accept()
bytes = serverSocket2.Receive(recByte)
IPEndPoint ep2 = (IPEndPoint)serverSocket2.RemoteEndPoint
Console.WriteLine(" from {0}", ep2.ToString())
recStr = Encoding.ASCII.GetString(recByte, 0, bytes)
Console.WriteLine("客户端2:{0}", recStr)
byte[] sendByte =Encoding.ASCII.GetBytes(ep1.ToString() + ":" + ep2.ToString())
serverSocket1.Send(sendByte, sendByte.Length, 0)
sendByte = Encoding.ASCII.GetBytes(ep2.ToString() + ":" + ep1.ToString())
serverSocket2.Send(sendByte, sendByte.Length, 0)
serverSocket1.Close()
serverSocket2.Close()
}
}
功能:两边客户端连接服务器后将映射的外网IP和端口号传给双方。
客户端代码
static void Main(string[] args)
{
string host = "115.21.X.X"//服务端IP地址
int port = 555
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
//设置端口可复用
clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true)
//连接服务端
clientSocket.Connect(host, port)
Console.WriteLine("Connect:" + host + " " + port)
string data = "hello,Server!"
clientSocket.Send(Encoding.ASCII.GetBytes(data))
Console.WriteLine("Send:" + data)
byte[] recBytes = new byte[100]
//获取到双方的ip及端口号
int bytes = clientSocket.Receive(recBytes, recBytes.Length, 0)
string result = Encoding.ASCII.GetString(recBytes, 0, bytes)
Console.WriteLine("Recv:" +result)
clientSocket.Close()
string[] ips = result.Split(':')
int myPort = Convert.ToInt32(ips[1])
string otherIp = ips[2]
int otherPort = Convert.ToInt32(ips[3])
Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
mySocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true)
//绑定到之前连通过的端口号
IPEndPoint ipe = new IPEndPoint(IPAddress.Any, Convert.ToInt32(myPort))
mySocket.Bind(ipe)
//尝试5次连接
for (int j = 0j <5j++)
{
try
{
mySocket.Connect(otherIp, otherPort)
Console.WriteLine("Connect:成功{0},{1}", otherIp,otherPort)
break
}
catch (Exception)
{
Console.WriteLine("Connect:失败")
// otherPort++//如果是对称NAT,则有可能客户端的端口号已经改变,正常有规律的应该是顺序加1,可以尝试+1再试(我使用手机热点连接的时候端口号就变成+1的了)除非是碰到随机端口,那就不行了。
}
}
while (true)
{
mySocket.Send(Encoding.ASCII.GetBytes("hello,the other client!"))
byte[] recv = new byte[4096]
int len = mySocket.Receive(recv, recv.Length, 0)
result = Encoding.ASCII.GetString(recv, 0, len)
Console.WriteLine("recv :" + result)
Thread.Sleep(1000)
}
}
另一边客户端也一样。连接服务器后,可以绑定之前的端口号复用,但如果碰到一端是对称NAT时每次使用端口号会不一样时,这样就得通过预测下次可能使用的端口号来连通。如:使用手机热点网络连接服务器时,获取到它使用的端口号是56324,等到下一次客户端互相连接使用56325才连上。
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)