您的位置:首页 > 理论基础 > 计算机网络

C#完整的通信代码(二)(点对点,点对多,同步,异步,UDP,TCP)

2010-03-20 14:20 701 查看
下列范例使用 UdpClient,在通讯端口  11000  监听广播到多点传送位址群组 224.168.100.2 的 UDP  资料包。它接收信息字串,并將信息写入主控台 (Console)。

C# code

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

public class UDPMulticastListener {

private static readonly IPAddress GroupAddress =

IPAddress.Parse("224.168.100.2");

private const int GroupPort = 11000;

private static void StartListener() {

bool done = false;

UdpClient listener = new UdpClient();

IPEndPoint groupEP = new IPEndPoint(GroupAddress,GroupPort);

try {

listener.JoinMulticastGroup(GroupAddress);

listener.Connect(groupEP);

while (!done) {

Console.WriteLine("Waiting for broadcast");

byte[] bytes = listener.Receive( ref groupEP);

Console.WriteLine("Received broadcast from {0} :/n {1}/n",

groupEP.ToString(),

Encoding.ASCII.GetString(bytes,0,bytes.Length));

}

listener.Close();

} catch (Exception e) {

Console.WriteLine(e.ToString());

}

}

public static int Main(String[] args) {

StartListener();

return 0;

}

}

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

public class UDPMulticastSender {

private static IPAddress GroupAddress =

IPAddress.Parse("224.168.100.2");

private static int GroupPort = 11000;

private static void Send( String message) {

UdpClient sender = new UdpClient();

IPEndPoint groupEP = new IPEndPoint(GroupAddress,GroupPort);

try {

Console.WriteLine("Sending datagram : {0}", message);

byte[] bytes = Encoding.ASCII.GetBytes(message);

sender.Send(bytes, bytes.Length, groupEP);

sender.Close();

} catch (Exception e) {

Console.WriteLine(e.ToString());

}

}

public static int Main(String[] args) {

Send(args[0]);

return 0;

}

}

C# code

try

{

UdpClient udp=new UdpClient(new IPEndPoint(ipAddress,startPort+i));

udp.Close();

unUsedPort=startPort+i;

break;

}

catch

{

}

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Collections;

using System.Collections.Specialized;

using System.Threading;

using System.Net.Sockets;

using System.Net;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Binary;

using System.IO;

namespace 聊天工具服务器

{

public partial class FormMain : Form

{

public FormMain()

{

InitializeComponent();

}

#region 字段定义

/// <summary>

/// 服务器程序使用的端口,默认为8888

/// </summary>

private int _port = 8888;

/// <summary>

/// 接收数据缓冲区大小2K

/// </summary>

private const int _maxPacket =2 * 1024;

/// <summary>

/// 服务器端的监听器

/// </summary>

private TcpListener _tcpl = null;

Thread _receiveThread;

/// <summary>

/// 保存所有客户端会话的哈希表

/// </summary>

private Hashtable _transmit_tb = new Hashtable();

/// <summary>

/// 当前文件路径

/// </summary>

string MyPath = null;

/// <summary>

/// 用户基本信息表,包括UserName,UserPwd,UserNich,UserImg,ZX,UserIp

/// </summary>

DataTable TabUser = new DataTable();

/// <summary>

/// 用户消息表,保存用户不在线时的消息

/// </summary>

DataTable TabUserMessage = new DataTable();

#endregion

/// <summary>

/// 序列化在线列表,向客户端返回序列化后的字节数组

/// </summary>

/// <returns>序列化后的字节数组 </returns>

private byte[] SerializeOnlineList()

{

StringCollection onlineList = new StringCollection();

foreach (object o in _transmit_tb.Keys)

{

onlineList.Add(o as string);

}

IFormatter format = new BinaryFormatter();

MemoryStream stream = new MemoryStream();

format.Serialize(stream, onlineList);

byte[] ret = stream.ToArray();

stream.Close();

return ret;

}

/// <summary>

/// 序列化好友列表,向客户端返回序列化后的datatable

/// </summary>

/// <returns>序列化后的字节数组 </returns>

private bool SerializeFriendList(object obj, Socket clientSkt)

{

DataTable TabmyFriend = new DataTable();

TabmyFriend.TableName = obj as string;

try {

TabmyFriend.ReadXml(MyPath + "//UserFriend//" + TabmyFriend.TableName + ".xml");

TabmyFriend.Columns.Add("UserImg", typeof(String));

TabmyFriend.Columns.Add("UserNich", typeof(String));

TabmyFriend.Columns.Add("ZX", typeof(Boolean));

TabmyFriend.Columns.Add("UserIp", typeof(String));

foreach (DataRow myrow in TabmyFriend.Rows)

{

DataRow[] DataRows = TabUser.Select(" UserName = '" + myrow["UserName"].ToString() + "'");

if (DataRows.Length > 0)

{

myrow["UserImg"] = DataRows[0]["UserImg"].ToString();

myrow["UserNich"] = DataRows[0]["UserNich"].ToString();

try

{

myrow["ZX"] = (bool)DataRows[0]["ZX"];

myrow["UserIp"] = DataRows[0]["UserIp"].ToString();

}

catch

{

myrow["ZX"] = false;

myrow["UserIp"] = "";

}

}

}

}

catch

{

TabmyFriend.Columns.Add("UserName", typeof(String));

TabmyFriend.Columns.Add("UserImg", typeof(String));

TabmyFriend.Columns.Add("ZX", typeof(Boolean));

TabmyFriend.Columns.Add("UserIp", typeof(String));

}

IFormatter format = new BinaryFormatter();

MemoryStream stream = new MemoryStream();

format.Serialize(stream, TabmyFriend);

stream.Position = 0;

byte[] ret = new byte[_maxPacket];

int count = 0;

count = stream.Read(ret, 0, _maxPacket);

//先发送响应信号,用户客户机的判断

clientSkt.Send(Encoding.Unicode.GetBytes("cmd::RequestFriendList"));

while (count >0)

{

clientSkt.Send(ret);

count =  stream.Read(ret, 0, _maxPacket);

}

//发送结束信号

clientSkt.Send(Encoding.Unicode.GetBytes("Find::RequestFriendListEnd"));

stream.Close();

return true ;

}

private void FormMain_Load(object sender, EventArgs e)

{

MyPath = Application.StartupPath;

Read_User();

ReadTabUserMessage();

_receiveThread = new Thread(new ThreadStart(StartUp));

_receiveThread.Start();

}

/// <summary>

/// 读取所有用户信息

/// </summary>

private void Read_User()

{

try

{

TabUser.ReadXml(MyPath + "//User.xml");

}

catch

{

TabUser.TableName = "User";

TabUser.Columns.Add("UserName", typeof(String));

TabUser.Columns.Add("UserPwd", typeof(String));

TabUser.Columns.Add("UserNich", typeof(String));

TabUser.Columns.Add("UserImg", typeof(String));

}

TabUser.Columns.Add("ZX", typeof(Boolean));

TabUser.Columns.Add("UserIp", typeof(String));

}

/// <summary>

/// 新用户上/下线后,更新其好友的(好友列表)

/// </summary>

/// <param name="UserName"> </param>

/// <param name="OnLine"> </param>

/// <param name="IpAddress"> </param>

private void UpdateFriendList(string UserName, bool OnLine, string IpAddress)

{

DataTable TabmyFriend = new DataTable();

TabmyFriend.TableName = UserName;

string svrlog = null;

string []UserInformation = new string[2];//UserName + "$" + IpAddress;

UserInformation[0] = UserName;

UserInformation[1] = IpAddress;

IFormatter format = new BinaryFormatter();

MemoryStream stream = new MemoryStream();

format.Serialize(stream, UserInformation);

byte[] ret = stream.ToArray();

stream.Close();

if (OnLine)

{

svrlog = "cmd::RequestAddFriendList";

}

else

{

svrlog = "cmd::RequestRemoveFriendList";

DataRow[] DataRows = TabUser.Select(" UserName = '" + UserName + "'");

if (DataRows.Length > 0)

{

DataRows[0]["ZX"] = false;

DataRows[0]["UserIp"] = "";

}

}

try

{

TabmyFriend.ReadXml(MyPath + "//UserFriend//" + TabmyFriend.TableName + ".xml");

foreach (DataRow myrow in TabmyFriend.Rows)

{

if(_transmit_tb.ContainsKey(myrow["UserName"].ToString()))

{

Socket _clientSkt = _transmit_tb[myrow["UserName"].ToString()] as Socket;

_clientSkt.Send(Encoding.Unicode.GetBytes(svrlog));

_clientSkt.Send(ret);

}

}

}

catch

{ }

}

[code=C#][/code /// <summary>

/// 线程执行体,转发消息

/// </summary>

/// <param name="obj">传递给线程执行体的用户名,用以与用户通信 </param>

private void ThreadFunc(object obj)

{

//通过转发表得到当前用户套接字

Socket clientSkt = _transmit_tb[obj] as Socket;

//主循环

while (true)

{

try

{

//接受第一个数据包。

//由于程序逻辑结构简单,所以在这里对客户机发送的第一个包内容作逐一判断,

//这里的实现不够优雅,但不失为此简单模型的一个解决之道。

byte[] packetBuff = new byte[_maxPacket];

clientSkt.Receive(packetBuff);

string _str = Encoding.Unicode.GetString(packetBuff).TrimEnd('/0');

//如果是发给不在线好友的信息

if (_str.StartsWith("cmd::FriendMessage"))

{

string UserName = _str.Substring("cmd::FriendMessage".Length, 20).Trim();

string MessageS = _str.Substring("cmd::FriendMessage".Length + 20, _str.Length - "cmd::FriendMessage".Length - 20);

SaveMessage(obj as string, UserName, MessageS);

continue;

}

//如果是离线请求

if (_str.StartsWith("cmd::RequestLogout"))

{

_transmit_tb.Remove(obj);

UpdateFriendList((string)obj, false, "");

//  string svrlog = string.Format("[系统消息]用户 {0} 在 {1} 已断开... 当前在线人数: {2}/r/n/r/n", obj, DateTime.Now, _transmit_tb.Count);

//  Console.WriteLine(svrlog);

//向所有客户机发送系统消息

//foreach (DictionaryEntry de in _transmit_tb)

//{

//    string _clientName = de.Key as string;

//    Socket _clientSkt = de.Value as Socket;

//    _clientSkt.Send(Encoding.Unicode.GetBytes(svrlog));

//}

Thread.CurrentThread.Abort();

}

//如果是请求好友列表

if (_str.StartsWith("cmd::RequestFriendList"))

{

SerializeFriendList(obj, clientSkt);

// 将该用户不在线时的信息发送给用户

DataTable TabMessage = ReadMessage(obj as string);

if (TabMessage != null)

{

foreach (DataRow myrow in TabMessage.Rows)

{

if (myrow["SendUserName"].ToString() == "System::Message")

{

clientSkt.Send(Encoding.Unicode.GetBytes(myrow["Message"].ToString()));

}

else

{

clientSkt.Send(Encoding.Unicode.GetBytes("cmd::FriendMessage" + myrow["SendUserName"].ToString().PadRight(20, ' ') + myrow["Message"].ToString()));

}

}

}

//这里不需要再继续接受后继数据包了,跳出当前循环体。

continue;

}

////如果是请求好友列表

//if (_str.StartsWith("cmd::RequestOnLineList"))

//{

//    byte[] onlineBuff = SerializeOnlineList();

//    //先发送响应信号,用户客户机的判断

//    clientSkt.Send(Encoding.Unicode.GetBytes("cmd::RequestOnLineList"));

//    clientSkt.Send(onlineBuff);

//    //这里不需要再继续接受后继数据包了,跳出当前循环体。

//    continue;

//}

//查找用户

if (_str.StartsWith("Find::FindFriend"))

{

DataTable TabFind = TabUser.Clone();

DataRow [] FindRow =null  ;

string UserName = _str.Substring("Find::FindFriend".Length, _str.Length - "Find::FindFriend".Length);

if (UserName.Equals("Find::WhoOnLine"))

{ //看谁在线

FindRow = TabUser.Select(" ZX = 1");

}

else//精确查找

{

FindRow = TabUser.Select("UserName = '" + UserName + "'");

}

foreach (DataRow myrow in FindRow)

{

TabFind.ImportRow(myrow);

}

clientSkt.Send(Encoding.Unicode.GetBytes("Find::FindFriend"));

IFormatter format = new BinaryFormatter();

MemoryStream stream = new MemoryStream();

format.Serialize(stream, TabFind);

stream.Position = 0;

byte[] ret = new byte[_maxPacket];

int count = 0;

count = stream.Read(ret, 0, _maxPacket);

while (count >0)

{

clientSkt.Send(ret);

count =  stream.Read(ret, 0, _maxPacket);

}

clientSkt.Send(Encoding.Unicode.GetBytes("Find::FindFriendEnd"));

stream.Close();

TabFind = null;

FindRow = null;

//这里不需要再继续接受后继数据包了,跳出当前循环体。

continue;

}

//请求添加好友

if (_str.StartsWith("Find::AddFriendAsk"))

{

string UserName = _str.Substring("Find::AddFriendAsk".Length, _str.Length - "Find::AddFriendAsk".Length);

//通过转发表查找接收方的套接字

if (_transmit_tb.Count != 0 && _transmit_tb.ContainsKey(UserName))

{

Socket receiverSkt = _transmit_tb[UserName] as Socket;

receiverSkt.Send(Encoding.Unicode.GetBytes("Find::AddFriendAsk" + obj as string));

}

//这里不需要再继续接受后继数据包了,跳出当前循环体。

continue;

}

//回复答应添加好友

if (_str.StartsWith("Find::AddFriendYes"))

{

string UserName = _str.Substring("Find::AddFriendYes".Length, _str.Length - "Find::AddFriendYes".Length);

//// 保存数据

DataTable TabmyFriend = new DataTable() ;

//保存该用户

TabmyFriend.ReadXml(MyPath + "//UserFriend//" +  obj as string + ".xml");

DataRow newRow = TabmyFriend.NewRow();

newRow["UserName"] = UserName;

TabmyFriend.Rows.Add(newRow);

TabmyFriend.WriteXml(MyPath + "//UserFriend//" + obj as string + ".xml", XmlWriteMode.WriteSchema, false);

//保存其好友

TabmyFriend = new DataTable();

TabmyFriend.ReadXml(MyPath + "//UserFriend//" + UserName + ".xml");

DataRow newRow1 = TabmyFriend.NewRow();

newRow1["UserName"] = obj as string;

TabmyFriend.Rows.Add(newRow1);

TabmyFriend.WriteXml(MyPath + "//UserFriend//" + UserName + ".xml", XmlWriteMode.WriteSchema, false);

TabmyFriend = null;

//更新好友列表

SerializeFriendList(obj, clientSkt);

上面发了服务器端,没发客户端,现在补上!不知道写的好不好,见笑了

C# code

public partial class Form1 : Form

{

private TcpClient client;

private bool isExit = false;

private NetworkStream networkStream;

private EventWaitHandle allDone = new EventWaitHandle(false, EventResetMode.ManualReset);

#region 用于一个线程操作另一个线程的控件

private delegate void SetListBoxCallback(string str);

private SetListBoxCallback setListBoxCallBack;

private delegate void SetRichTextBoxCallback(string str);

private SetRichTextBoxCallback setRichTextBoxCallBack;

#endregion

public Form1()

{

InitializeComponent();

listBoxStatus.HorizontalScrollbar = true;

setListBoxCallBack = new SetListBoxCallback(SetListBox);

setRichTextBoxCallBack = new SetRichTextBoxCallback(SetReceiveText);

}

//状态显示

private void SetListBox(string str)

{

listBoxStatus.Items.Add(str);

listBoxStatus.SelectedIndex = listBoxStatus.Items.Count - 1;

listBoxStatus.ClearSelected();

}

//接收客户端信息

private void SetReceiveText(string str)

{

richTextBoxReceive.AppendText(str);

}

//连接服务器....

private void buttonConnet_Click(object sender, EventArgs e)

{

client = new TcpClient(AddressFamily.InterNetwork);

//得到服务器IP

IPAddress ip= IPAddress.Parse("127.0.0.1");

//创建一个委托,并知名在异步操作完成时执行的方法

AsyncCallback callback = new AsyncCallback(RequestCallBack);

allDone.Reset();

client.BeginConnect(ip, 7100, RequestCallBack, client);

}

private void RequestCallBack(IAsyncResult ar)

{

allDone.Set();

try

{

client = (TcpClient)ar.AsyncState;

client.EndConnect(ar);

listBoxStatus.Invoke(setListBoxCallBack, string.Format("与服务器{0}连接成功", client.Client.RemoteEndPoint));

networkStream = client.GetStream();

ReadObject readObject = new ReadObject(networkStream, client.ReceiveBufferSize);

networkStream.BeginRead(readObject.bytes, 0, readObject.bytes.Length, ReadCallBack, readObject);

}

catch (Exception e1)

{

listBoxStatus.Invoke(setListBoxCallBack, e1.Message);

return;

}

}

//异步操作完成时执行的回调调用的方法

private void ReadCallBack(IAsyncResult ar)

{

try

{

ReadObject ro = (ReadObject)ar.AsyncState;

int count = ro.netStream.EndRead(ar);

richTextBoxReceive.Invoke(setRichTextBoxCallBack, System.Text.Encoding.UTF8.GetString(ro.bytes, 0, count));

if (isExit == false)

{

ro = new ReadObject(networkStream, client.ReceiveBufferSize);

networkStream.BeginRead(ro.bytes, 0, ro.bytes.Length, ReadCallBack, ro);

}

}

catch (Exception e2)

{

listBoxStatus.Invoke(setListBoxCallBack, e2.Message);

return;

}

}

//发送数据

private void SendString(string str)

{

try

{

byte[] by = System.Text.Encoding.UTF8.GetBytes(str+"/r/n");

networkStream.BeginWrite(by, 0, by.Length, new AsyncCallback(SendCallBack), networkStream);

networkStream.Flush();

}catch(Exception e3){

listBoxStatus.Invoke(setListBoxCallBack, e3.Message);

return;

}

}

//发送数据回调的方法

private void SendCallBack(IAsyncResult ar)

{

try

{

networkStream.EndWrite(ar);

}

catch (Exception e4)

{

listBoxStatus.Invoke(setListBoxCallBack, e4.Message);

return;

}

}

private void buttonSend_Click(object sender, EventArgs e)

{

SendString(richTextBoxSend.Text);

richTextBoxSend.Clear();

}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)

{

isExit = true;

allDone.Set();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐