Server.cs   服务端程序

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets; namespace SocketTest
{
public partial class Server : Form
{
Thread serverThread; //服务端线程
Thread clientThread; //客户端线程
Socket serverSocket; //服务端socket
Socket clientSocket; //客户端socket public Server()
{
InitializeComponent();
} private void ServerStart()
{
//创建IPEndPoint实例
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, );
//创建一个套接字
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//将所创建的套接字与IPEndPoint绑定
serverSocket.Bind(ipep);
//设置套接字为收听模式
serverSocket.Listen(); /**
* 通过serverSocket.Accept()来接收客户Socket的连接请求,
* 在这里用循环可以实现该线程实时侦听,而不是只侦听一次。
* 当程序运行serverSocket.Accept()时,会等待,直到有客户端Socket发起连接请求时,
* 获取该客户Socket,如上面的clientSocket。在这里我用多线程来实现与多个客户端Socket的连接和通信,
* 一旦接收到一个连接后,就新建一个线程,执行ReceiveData功能来实现信息的发送和接收。
*/
while (true)
{
try
{
//在套接字上接收接入的连接
clientSocket = serverSocket.Accept();
clientThread = new Thread(new ThreadStart(ReceiveData));
clientThread.Start();
}
catch (Exception ex)
{
MessageBox.Show("listening Error: " + ex.Message);
}
}
} /**
* 通过IPEndPoint clientep = (IPEndPoint)s.RemoteEndPoint;
* 我们可以获取连接上的远程主机的端口和IP地址,如果想查询该主机的其它属性如主机名等,
* 可用于上一篇讲的Dns.GetHostByAddress(string ipAddress)来返回一个IPHostEntry对象,就可以得到。
* 另外我们要注意的是,通过Socket发送信息,必须要先把发送的信息转化成二进字进行传输,
* 收到信息后也要把收到的二进字信息转化成字符形式,
* 这里可以通过Encoding.ASCII.GetBytes(welcome);和Encoding.ASCII.GetString(buffer).Substring(0, bufLen);来实现。
* 以上就是服务端Socket侦听模式的实现,只要有远程客户端Socket连接上后,就可以轻松的发送信息和接收信息了。
* 下面我们来看看客户端Socket是怎么连接上服务器的。
**/
private void ReceiveData()
{
bool keepalive = true;
Socket s = clientSocket;
Byte[] buffer = new Byte[];
//根据收听到的客户端套接字向客户端发送信息
IPEndPoint clientep = (IPEndPoint)s.RemoteEndPoint;
this.Invoke(new MethodInvoker(() =>
{
lstServer.Items.Add("Client:" + clientep.Address + "(" + clientep.Port + ")");
}));
string welcome = "Welcome to my test sever ";
byte[] data = new byte[];
data = Encoding.ASCII.GetBytes(welcome);
s.Send(data, data.Length, SocketFlags.None);
while (keepalive)
{
//在套接字上接收客户端发送的信息
int bufLen = ;
try
{
bufLen = s.Available;
s.Receive(buffer, , bufLen, SocketFlags.None);
if (bufLen == )
continue;
}
catch (Exception ex)
{
MessageBox.Show("Receive Error:" + ex.Message);
return;
}
clientep = (IPEndPoint)s.RemoteEndPoint;
string clientcommand = System.Text.Encoding.ASCII.GetString(buffer).Substring(, bufLen);
this.Invoke(new MethodInvoker(() =>
{
lstServer.Items.Add(clientcommand + "(" + clientep.Address + ":" + clientep.Port + ")");
}));
}
} private void btnOpen_Click(object sender, EventArgs e)
{
serverThread = new Thread(new ThreadStart(ServerStart));
serverThread.Start();
lstServer.Items.Add("Server Start .....");
}
}
}

Client.cs(客户端程序)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading; namespace Client
{
public partial class Client : Form
{
Socket clientSocket;
Thread clientThread; public Client()
{
InitializeComponent();
} /**
* 客户端Socket连接相对来说比较简单了,另外说明一下,在执行客户端连接前,服务端Socket侦听必须先启动,
* 不然会提示服务器拒绝连接的信息。
* 客户端的发送信息和接收信息跟服务器的接收发送是一样的,只不过一个是侦听模式而另一个是连接模式。
* 另外提一下,这里服务端开启侦听服务、客户端连接服务端都采用线程方式来实现,这样服务端能够跟多个客户端同时通信,不用等候,
* 当然还有另外一种方式可以实现那就是异步socket.
*/
private void ConnectToServer()
{
byte[] data = new byte[];
//创建一个套接字
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), );
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//将套接字与远程服务器地址相连
try
{
clientSocket.Connect(ipep);
}
catch (SocketException ex)
{
MessageBox.Show("connect error: " + ex.Message);
return;
}
while (true)
{
//接收服务器信息
int bufLen = ;
try
{
bufLen = clientSocket.Available;
clientSocket.Receive(data, , bufLen, SocketFlags.None);
if (bufLen == )
{
continue;
}
}
catch (Exception ex)
{
MessageBox.Show("Receive Error:" + ex.Message);
return;
}
string clientcommand = System.Text.Encoding.ASCII.GetString(data).Substring(, bufLen);
this.Invoke(new MethodInvoker(() =>
{
lstClient.Items.Add(clientcommand);
}));
//clientSocket.Shutdown(SocketShutdown.Both);
//clientSocket.Close();
}
} private void button1_Click(object sender, EventArgs e)
{
clientThread = new Thread(new ThreadStart(ConnectToServer));
clientThread.Start();
} private void btnSend_Click(object sender, EventArgs e)
{
//向服务器发送信息
byte[] data = new byte[];
data = Encoding.ASCII.GetBytes(txtClient.Text);
clientSocket.Send(data, data.Length, SocketFlags.None);
}
}
}

最新文章

  1. vector
  2. POJ 1743 Musical Theme 二分+后缀数组
  3. js使用模板快速填充数据
  4. SQL注入的常用函数和语句
  5. 【转】ora-00031:session marked for kill处理oracle中杀不掉的锁
  6. BZOJ2120 数颜色
  7. UVALive 6692 Lucky Number (思路 + 枚举)
  8. RMAN学习笔记
  9. ServletRequest接口召回总结
  10. 达到工业使用质量级别的类似于QQ截屏的软件
  11. IOS的UIPickerView 和UIDatePicker
  12. TypeError: Error #1034: 强制转换类型失败:无法将 "0.49" 转换为 mx.graphics.IFill。
  13. codechef February Challenge 2018 简要题解
  14. MySQL联合索引VS单列索引
  15. C#_02.14_基础五_.NET类
  16. Cmd Markdown 编辑阅读器
  17. 关于想通过ros的dstnat实现公网IP nat 公网IP的情况
  18. C++中返回值
  19. iptables说明(转)
  20. Redis字符串操作

热门文章

  1. VMware Workstation 虚拟机设置连接U盘
  2. C/C++知识要点2——STL中Vector、Map、Set容器的实现原理
  3. C# - CLR
  4. JS判断访问设备(userAgent)加载不同页面 JS判断客户端操作系统类型(platform)
  5. BusHelper
  6. 常用的sql命令
  7. JUNO eclipse Version: 4.2.0 添加svn插件
  8. ubuntu12.04配置NFS服务详解
  9. CUE 文件格式说明
  10. vue文档重读有感