.NET中Socket编程的简单示例

作者:网络 来源:佚名 更新时间:2008-07-07 19:06:43 点击:

以下示例程序实现简单的socket通信,可以开多个客户端。本机测试通过,未做联机测试。

server:

using system.net;

using system.net.sockets;

using system.threading;

using system.collections;

 

namespace mysocketserver1

{

    public partial class form1 : form

    {

        private ipaddress serverip = ipaddress.parse("127.0.0.1");//以本机作测试

        private ipendpoint serverfulladdr;//完整终端地址

        private socket sock;

        private system.timers.timer mytimer;

        private arraylist alsock;//当建立了多个连接时用于保存连接

 

        public form1()

        {

            initializecomponent();

        }

 

        private void btstart_click(object sender, eventargs e)

        {

            serverfulladdr = new ipendpoint(serverip, 1000);//取端口号1000

//构造socket对象,套接字类型为“流套接字”,指定五元组中的协议元

            sock = new socket(addressfamily.internetwork, sockettype.stream,

protocoltype.tcp);

//指定五元组中的本地二元,即本地主机地址和端口号

            sock.bind(serverfulladdr);

//监听是否有连接传入,指定挂起的连接队列的最大值为20

            sock.listen(20);

 

            alsock = new arraylist();

 

//构造定时器,时间间隙为1秒,即每隔一秒执行一次accept()方法,以获取连接请求队列中//第一个挂起的连接请求

            mytimer =new system.timers.timer(1000);

            mytimer.elapsed +=new system.timers.elapsedeventhandler(mytimer_elapsed);

            mytimer.enabled = true;

        }

 

        private void mytimer_elapsed(object sender, system.timers.elapsedeventargs e)

        {

            mytimer.enabled = false;

//执行accept(),当挂起队列为空时将阻塞本线程,同时由于上一语句,定时器将停止,直//至有连接传入

            socket acceptsock = sock.accept();

//将accept()产生的socket对象存入arraylist

            alsock.add(acceptsock);

// 构造threading.timer对象,这将导致程序另启线程。线程将执行回调函数,该委托限制//函数参数须为object型。threading.timer构造器的第二个参数即传入回调函数的参数;第//三个参数指定调用回调函数之前的延时,取0则立即启动;最后一个参数指定调用回调函数//的时间间隔,取0则只执行一次。

            system.threading.timer ti = new system.threading.timer(new

timercallback(receivemsg), acceptsock, 0, 0);

            mytimer.enabled = true;

        }

 

        private void receivemsg(object obj)

        {

            socket acceptsock = (socket)obj;

            try

            {

                while (true)

                {

                    byte[] bytearray = new byte[100];

                    acceptsock.receive(bytearray);//接收数据

//将字节数组转成字符串

                    string strrec = system.text.encoding.utf8.getstring(bytearray);

                    if (this.rtbreceive.invokerequired)

                    {

                        this.rtbreceive.invoke(new eventhandler(this.changericktextbox), new

object[] { strrec, eventargs.empty });

                    }

                }

            }

            catch(exception ex)

            {

                acceptsock.close();

                messagebox.show("s:receive message error"+ex.message);

            }

        }

 

        private void changericktextbox(object obj,eventargs e)

        {

            string s = system.convert.tostring(obj);

            this.rtbreceive.appendtext(s + environment.newline);

        }

 

        private void btsend_click(object sender, eventargs e)

        {

            socket sc=null;

            byte[] bytesend =

system.text.encoding.utf8.getbytes(this.tbsend.text.tochararray());

            try

            {

//同时存在若干个客户端连接时,在textbox1中输入要发送的是哪个连接

                int index = int.parse(this.textbox1.text.trim());

                sc = (socket)alsock[index - 1];

//发送数据

                sc.send(bytesend);

            }

            catch(exception ex)

            {

if(sc != null)

{

                sc.close();

}

                messagebox.show("s:send message error"+ex.message);

            }

        }

 

        private void btclose_click(object sender, eventargs e)

        {

            try

            {

                application.exit();

            }

            catch (exception ex)

            {

                messagebox.show("s:close socket error" + ex.message);

            }

        }

    }

}

== == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==

client:

using system.net;

using system.net.sockets;

using system.threading;

 

namespace mysocketclient1

{

    public partial class form1 : form

    {

        private ipaddress serverip = ipaddress.parse("127.0.0.1");

        private ipendpoint serverfulladdr;

        private socket sock;

 

        public form1()

        {

            initializecomponent();

        }

 

        private void btconnect_click(object sender, eventargs e)

        {

            try

            {

                serverfulladdr = new ipendpoint(serverip, 1000);

                sock = new socket(addressfamily.internetwork, sockettype.stream,

protocoltype.tcp);

                sock.connect(serverfulladdr);//建立与远程主机的连接

 

//启动新线程用于接收数据

                thread t = new thread(new threadstart(receivemsg));

                t.name = "receive message";

//一个线程或者是后台线程或者是前台线程。后台线程与前台线程类似,区别是后台线//程不会防止进程终止。一旦属于某一进程的所有前台线程都终止,公共语言运行库就//会通过对任何仍然处于活动状态的后台线程调用 abort 来结束该进程。

                t.isbackground = true;

                t.start();

            }

            catch(exception ex)

            {

                messagebox.show(ex.message);

            }

        }

 

        private void receivemsg()

        {

            try

            {

                while (true)

                {

                    byte[] byterec = new byte[100];

                    this.sock.receive(byterec);

                    string strrec = system.text.encoding.utf8.getstring(byterec);

                    if (this.rtbreceive.invokerequired)

                    {

                        this.rtbreceive.invoke(new eventhandler(changertb), new object[]

{ strrec, eventargs.empty });

                    }

                }

            }

            catch(exception ex)

            {

                messagebox.show("receive message error"+ex.message);

            }

        }

 

        private void changertb(object obj, eventargs e)

        {

            string s = system.convert.tostring(obj);

            this.rtbreceive.appendtext(s + environment.newline);

        }

 

        private void btsend_click(object sender, eventargs e)

        {

            byte[] bytesend =

system.text.encoding.utf8.getbytes(this.tbsend.text.tochararray());

            try

            {

                this.sock.send(bytesend);

            }

            catch

            {

                messagebox.show("send message error");

            }

        }

 

        private void btclose_click(object sender, eventargs e)

        {

            try

            {

                this.sock.shutdown(socketshutdown.receive);

                this.sock.close();

                application.exit();

            }

            catch

            {

                messagebox.show("exit error");

            }

        }

    }

}

不解之处:

client端红色标注语句:this.sock.shutdown(socketshutdown.receive),如改成

this.sock.shutdown(socketshutdown.both);或this.sock.shutdown(socketshutdown.send);

则当点击cloce按钮时,cpu使用率疯涨到100%,而使用this.sock.shutdown(socketshutdown.receive);

或不调用shutdown()方法则没有这个问题。难道客户端不应该用shutdown()?