以下示例程序实现简单的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()?
http://www.cnblogs.com/kissknife/archive/2006/08/13/475707.html