- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章基于c#用Socket做一个局域网聊天工具由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
程序设计成为简单的服务端和客户端之间的通信, 但通过一些方法可以将这两者进行统一起来, 让服务端也成为客户端, 让客户端也成为服务端, 使它们之间可以互相随时不间断的通信. 考虑到实现最原始的服务端和客户端之间的通信所需要的步骤对于写这样的程序是很有帮助的. 。
作为服务端, 要声明一个socket a并绑定(bind)某一个ip+这个ip指定的通信端口, 比如这个是127.0.0.1:9050, 然后开始监听(listen), listen可以监听来自多个ip传过来的连接请求, 具体可以同时连接几个客户端, listen方法中可以设定一个参数. 如果listen到某一个客户端发来连接请求了, 这时定义一个新的socket b专门负责与这个客户端的通信, socket b = a.accept(). 这时可以获取这个客户端的ip和端口, ipendpoint c = (ipendpoint)b.remoteendpoint, c.address和c.port分别表示客户端c的ip地址和端口. 这时通过b.send()方法就可以给c发送消息了, b.receive()可以接收客户端c发来的信息. 。
作为客户端, 也需要声明一个socket d并绑定某一个ip+本机一个未被占用的端口, 定义ipendpoint e表示要进行连接的服务端socket, 要指明e的ip和端口, 这样才可以进行端口对端口之间的通信, 接下来就可以尝试d.connect(e), 连接成功之后就可以发送和接收数据了, d.send(), d.receive. 。
发送消息时, 数据都是以字节或字节数组为单位进行传输的, 比如我客户端d要发送"hello world"则要这样写: d.send(encoding.ascii.getbytes("hello world")). 接受消息时, 也是以字节或字节数组, 比如服务端要接受d刚才发送的hello world, 可以这样写: byte[] data = new byte[1024]; int receiveddatalength = b.receive(data); string stringdata = encoding.ascii.getstring(data, 0, receiveddatalength); stringdata这时就是hello world. 。
上面只是大概的阐述了服务端与客户端之间的通信过程, 在网上找到了具体的代码例子, 也贴过来参考参考. 这个例子没有将服务端与客户端统一起来, 他是分别写服务端和客户端的. 。
服务端代码 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
using
system;
using
system;
using
system.net;
using
system.net.sockets;
using
system.text;
namespace
tcpserver
{
/// <summary>
/// class1 的摘要说明。
/// </summary>
class
server
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[stathread]
static
void
main(
string
[] args)
{
//
// todo: 在此处添加代码以启动应用程序
//
int
recv;
// 用于表示客户端发送的信息长度
byte
[] data;
// = new byte [ 1024 ]; // 用于缓存客户端所发送的信息,通过socket传递的信息必须为字节数组
ipendpoint ipep =
new
ipendpoint(ipaddress.any, 9050 );
// 本机预使用的ip和端口
socket newsock =
new
socket(addressfamily.internetwork,sockettype.stream,protocoltype.tcp);
newsock.bind(ipep);
// 绑定
newsock.listen( 10 );
// 监听
console.writeline(
" waiting for a client "
);
socket client = newsock.accept();
//当有可用的客户端连接尝试时执行,并返回一个新的socket,用于与客户端之间的通信
ipendpoint clientip = (ipendpoint)client.remoteendpoint;
console.writeline(
" connect with client: "
+ clientip.address +
" at port: "
+ clientip.port);
string
welcome =
" welcome here! "
;
data = encoding.ascii.getbytes(welcome);
client.send(data,data.length,socketflags.none);
// 发送信息
while
(
true
)
{
// 用死循环来不断的从客户端获取信息
data =
new
byte
[ 1024 ];
recv = client.receive(data);
console.writeline(
" recv= "
+ recv);
if
(recv == 0 )
// 当信息长度为0,说明客户端连接断开
break
;
console.writeline(encoding.ascii.getstring(data, 0 ,recv));
client.send(data,recv,socketflags.none);
}
console.writeline(
" disconnected from "
+ clientip.address);
client.close();
newsock.close();
}
}
}
|
客户端代码 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
using
system;
using
system.net;
using
system.net.sockets;
using
system.text;
namespace
tcpclient
{
/// <summary>
/// class1 的摘要说明。
/// </summary>
class
client
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[stathread]
static
void
main(
string
[] args)
{
//
// todo: 在此处添加代码以启动应用程序
//
byte
[] data =
new
byte
[1024];
socket newclient =
new
socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp);
newclient.bind(
new
ipendpoint(ipaddress.any, 905));
console.write(
" please input the server ip: "
);
string
ipadd = console.readline();
console.writeline();
console.write(
" please input the server port: "
);
int
port = convert.toint32(console.readline());
ipendpoint ie =
new
ipendpoint(ipaddress.parse(ipadd), port);
// 服务器的ip和端口
try
{
// 因为客户端只是用来向特定的服务器发送信息,所以不需要绑定本机的ip和端口。不需要监听。
newclient.connect(ie);
}
catch
(socketexception e)
{
console.writeline(
" unable to connect to server "
);
console.writeline(e.tostring());
return
;
}
int
receiveddatalength = newclient.receive(data);
string
stringdata = encoding.ascii.getstring(data, 0, receiveddatalength);
console.writeline(stringdata);
while
(
true
)
{
string
input = console.readline();
if
(input ==
" exit "
)
break
;
newclient.send(encoding.ascii.getbytes(input));
data =
new
byte
[1024];
receiveddatalength = newclient.receive(data);
stringdata = encoding.ascii.getstring(data, 0, receiveddatalength);
console.writeline(stringdata);
}
console.writeline(
" disconnect from sercer "
);
newclient.shutdown(socketshutdown.both);
newclient.close();
}
}
}
|
上面的服务端和客户端都是控制台应用程序, 想办法做一个窗体类型的, 思路就是另起一个线程, 这个线程专门负责两端建立连接. 如果不采用另起线程的方法, 当等待连接而没有连接上, 或者主动连接, 服务端还没有相应时, 程序就会出现没有响应的假死状态. 。
当这个线程将两个端口连接成功后, 就让程序进入一个死循环, 这个死循环负责不断的接收是否有消息传来, 传来的话就在txtgetmsg中显示出来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
while
(
true
)
// 用死循环来不断的获取信息
{
data =
new
byte
[1024];
recv = newclient.receive(data);
uicontext.send(
new
sendorpostcallback(
state =>
{
int
txtgetmsglength = txtgetmsg.text.length;
string
recmsg =
"friend: "
+ system.datetime.now.tostring() +
"\n "
+encoding.unicode.getstring(data, 0, recv) +
"\n"
;
txtgetmsg.appendtext(recmsg);
txtgetmsg.select(txtgetmsglength, recmsg.length - encoding.unicode.getstring(data, 0, recv).length - 1);
txtgetmsg.selectioncolor = color.red;
}),
null
);
}
|
如果按下发送消息的按钮, 则发送txtsendmsg中的文本, 我写的是用unicode编码, 所以可以发送中文字符. 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
private
void
btnsendmsg_click(
object
sender, eventargs e)
{
string
input = txtsendmsg.text;
if
(input ==
""
)
{
messagebox.show(
"消息不能为空!"
,
"发送消息出错"
);
txtsendmsg.focus();
}
else
{
if
(meisclient)
{
newclient.send(encoding.unicode.getbytes(input));
string
showtext =
"me: "
+ system.datetime.now.tostring() +
"\n "
+ input +
"\n"
;
int
txtgetmsglength = txtgetmsg.text.length;
txtgetmsg.appendtext(showtext);
txtgetmsg.select(txtgetmsglength, showtext.length - 1 - input.length);
txtgetmsg.selectioncolor = color.blue;
txtsendmsg.text =
""
;
}
else
{
client.send(encoding.unicode.getbytes(input));
string
showtext =
"me "
+ system.datetime.now.tostring() +
"\n "
+ input +
"\n"
;
int
txtgetmsglength = txtgetmsg.text.length;
txtgetmsg.appendtext(showtext);
txtgetmsg.select(txtgetmsglength, showtext.length - 1 - input.length);
txtgetmsg.selectioncolor = color.blue;
txtsendmsg.text =
""
;
}
}
}
|
程序的运行效果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
最后此篇关于基于c#用Socket做一个局域网聊天工具的文章就讲到这里了,如果你想了解更多关于基于c#用Socket做一个局域网聊天工具的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在谈论 UDP 时,我看到/听到了几次拥塞。这是什么意思? 最佳答案 拥塞是指当您尝试在有限带宽上发送过多数据时,它发送数据的速度无法比传入数据快,因此会丢弃额外的数据包。 发生拥塞时,您可以看到这些
我想让 Xdebug 在办公室的 LAN 上以半安全的方式运行。我们当前的设置如下: 192.168.1.1 下 LAN 网络上的本地服务器与 Ubuntu Server 16 在 Ubuntu 服务
我是一名优秀的程序员,十分优秀!