c#socket TCP同步网络通信
一、socket简介
socket就是套接字,它是引用网络连接的特殊文件描述符,由三个基本要素组成:
1: addressfamily(网络类型)
2: sockettype(数据传输类型)
3:protocoltype(采用的网络协议)
下面是可用于ip通信的套接字组合及其常用的属性和方法
二、socket与网络通信
ip连接领域有两种通信类型:面向连接的和无连接的,这里我要讲的是面向连接的,使用tcp协议来建立两个ip的值端点之间的会话,下面是它的基本步骤。
a:建立一个套接字
b:绑定本机的ip和端口
c:使用listen()方法监听别人发过来的东西
d:如果监听到连接,则可以使用send/receive来执行操作
e:完成后使用close()方法进行关闭
工作原理如图所示:
三、一个简单的同步通信示例
1.服务器端
using system.text;
using system.threading.tasks;
using system.net;
using system.net.sockets;
using system.threading;
namespace socket服务端
{
class program
{
static void main(string[] args)
{
int port = 23456;//端口号
int recv;//记录客户端信息的长度
string address = "127.0.0.1";//ip地址,指向localhost主机名,常用于程序调试
ipaddress addr = ipaddress.parse(address);
ipendpoint ipe = new ipendpoint(addr, port);
socket socket = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp);
socket.bind(ipe);//绑定端口
socket.listen(0);//开始监听,0表示任意数量
console.writeline("已启动监听,等待客户端连接。");
socket clientsocket = socket.accept();
ipendpoint clientip = (ipendpoint)clientsocket.remoteendpoint;//获取远程终结点信息
if (clientsocket != null)
console.writeline("成功与{0}的客户端建立联系",clientip);
while (true)//用死循环不断执行
{
try
{
byte[] data = new byte[1024];
recv = clientsocket.receive(data);//获取客户端传过来的信息
if (recv == 0)
break;
console.writeline("客户端发来信息:{0}",encoding.ascii.getstring(data, 0, recv));
console.write("输入要发送的信息:");
string input = console.readline();
clientsocket.send(encoding.ascii.getbytes(input));
}
catch(exception ex)
{
console.writeline("error:{0}", ex.message);
}
}
console.writeline("断开连接");
clientsocket.close();
socket.close();
}
}
}
2.客户端
using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
using system.net;
using system.net.sockets;
namespace socket客户端
{
class program
{
static void main(string[] args)
{
int port = 23456;
string address = "127.0.0.1";
byte[] data = new byte[1024];
ipaddress addr = ipaddress.parse(address);
ipendpoint ipe = new ipendpoint(addr, port);
socket socket = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp);
socket.connect(ipe);
console.writeline("与服务器连接成功");
try
{
while (true)
{
console.write("输入信息内容:");
string input = console.readline();
if (input == "exit")
break;
socket.send(encoding.ascii.getbytes(input));//发送数据
data = new byte[1024];
int recv;
string strdata;
recv = socket.receive(data);
strdata = encoding.ascii.getstring(data, 0, recv);
console.writeline("服务器发来内容:{0}",strdata);
}
}
catch (socketexception ex)
{
console.writeline(ex.tostring());
}
console.writeline("断开连接...");
socket.shutdown(socketshutdown.both);
socket.close();
console.readkey();
}
}
}
接下来对上面一些内容进行解释
a.端口号:32位无符号整形,范围是0~65535,0~1023被系统进程和通信协议使用,1024~49251是用户可以使用的端口
b.ipaddress类: 该类有一个parse()方法,可以把点分的十进制ip转化为ipadress类, 它还有四个可读字段
any:用于代表本地系统可用的任何ip地址
broadcase:用于代表本地网络的ip广播地址
loopback:用于代表本地系统的回送地址
none:用于代表本地系统上没有网络接口
c.ipendpoint是一个端口和ip地址的绑定,可以代表一个服务,用来socket通信,可以通过两种方法构造
ipendpoint( long address, int pot);
ipendpoint( ipaddress address, int pot)'
d. accept 以同步方式从侦听套接字,在连接请求队列中提取第一个挂起的连接请求,然后创建并返回一个新socket。 不能使用此返回socket为接受任何其他连接的连接队列。 但是,可以调用remoteendpoint方法所返回的socket来标识远程主机的网络地址和端口号。
e.receive()从绑定的 socket套接字接收数据,将数据存入接收缓冲区。
注:同步通信每发完一个数据包后,需要等待接收方响应后再继续发送下一个数据包
运行时先启动服务器端,再启动客户端