网络课的project 1能用到的资料,程序结构比较清晰,转来学习一下
什么是异步通讯?
就是通讯任意一方可以任意发送消息,有消息来到时会收到系统提示去接收消息。
这里要用到select函数。使用步骤如下:
1、设置一个集合变量,用来存放所有要判断的句柄(file descriptors:即我们建立的每个socket、用open打开的每个文件等)
2、把需要判断的句柄加入到集合里
3、设置判断时间
4、开始等待,即select
5、如果在设定的时间内有任何句柄状态变化了就马上返回,并把句柄设置到集合里
服务器端源代码如下:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/types.h>
#define MAXBUF 1024
/************关于本文档********************************************
*filename: async-server.c
*purpose: 演示网络异步通讯,这是服务器端程序
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com
)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-25 21:22
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to: Google.com
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int
main(
int
argc,
char
**argv)
{
int
sockfd, new_fd;
socklen_t len;
struct
sockaddr_in my_addr, their_addr;
unsigned
int
myport, lisnum;
char
buf[MAXBUF + 1];
fd_set rfds;
struct
timeval tv;
int
retval, maxfd = -1;
if
(argv[1])
myport =
atoi
(argv[1]);
else
myport = 7838;
if
(argv[2])
lisnum =
atoi
(argv[2]);
else
lisnum = 2;
if
((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror
(
"socket"
);
exit
(1);
}
bzero(&my_addr,
sizeof
(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(myport);
if
(argv[3])
my_addr.sin_addr.s_addr = inet_addr(argv[3]);
else
my_addr.sin_addr.s_addr = INADDR_ANY;
if
(bind(sockfd, (
struct
sockaddr *) &my_addr,
sizeof
(
struct
sockaddr))
== -1) {
perror
(
"bind"
);
exit
(1);
}
if
(listen(sockfd, lisnum) == -1) {
perror
(
"listen"
);
exit
(1);
}
while
(1) {
printf
(
"\n----等待新的连接到来开始新一轮聊天……\n"
);
len =
sizeof
(
struct
sockaddr);
if
((new_fd =
accept(sockfd, (
struct
sockaddr *) &their_addr,
&len)) == -1) {
perror
(
"accept"
);
exit
(
errno
);
}
else
printf
(
"server: got connection from %s, port %d, socket %d\n"
,
inet_ntoa(their_addr.sin_addr),
ntohs(their_addr.sin_port), new_fd);
/* 开始处理每个新连接上的数据收发 */
printf
(
"\n准备就绪,可以开始聊天了……直接输入消息回车即可发信息给对方\n"
);
while
(1) {
/* 把集合清空 */
FD_ZERO(&rfds);
/* 把标准输入句柄0加入到集合中 */
FD_SET(0, &rfds);
maxfd = 0;
/* 把当前连接句柄new_fd加入到集合中 */
FD_SET(new_fd, &rfds);
if
(new_fd > maxfd)
maxfd = new_fd;
/* 设置最大等待时间 */
tv.tv_sec = 1;
tv.tv_usec = 0;
/* 开始等待 */
retval = select(maxfd + 1, &rfds, NULL, NULL, &tv);
if
(retval == -1) {
printf
(
"将退出,select出错! %s"
,
strerror
(
errno
));
break
;
}
else
if
(retval == 0) {
/* printf
("没有任何消息到来,用户也没有按键,继续等待……\n"); */
continue
;
}
else
{
if
(FD_ISSET(0, &rfds)) {
/* 用户按键了,则读取用户输入的内容发送出去 */
bzero(buf, MAXBUF + 1);
fgets
(buf, MAXBUF, stdin);
if
(!strncasecmp(buf,
"quit"
, 4)) {
printf
(
"自己请求终止聊天!\n"
);
break
;
}
len = send(new_fd, buf,
strlen
(buf) - 1, 0);
if
(len > 0)
printf
(
"消息:%s\t发送成功,共发送了%d个字节!\n"
,
buf, len);
else
{
printf
(
"消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n"
,
buf,
errno
,
strerror
(
errno
));
break
;
}
}
if
(FD_ISSET(new_fd, &rfds)) {
/* 当前连接的socket上有消息到来则接收对方发过来的消息并显示 */
bzero(buf, MAXBUF + 1);
/* 接收客户端的消息 */
len = recv(new_fd, buf, MAXBUF, 0);
if
(len > 0)
printf
(
"接收消息成功:'%s',共%d个字节的数据\n"
,
buf, len);
else
{
if
(len < 0)
printf
(
"消息接收失败!错误代码是%d,错误信息是'%s'\n"
,
errno
,
strerror
(
errno
));
else
printf
(
"对方退出了,聊天终止\n"
);
break
;
}
}
}
}
close(new_fd);
/* 处理每个新连接上的数据收发结束 */
printf
(
"还要和其它连接聊天吗?(no->退出)"
);
fflush
(stdout);
bzero(buf, MAXBUF + 1);
fgets
(buf, MAXBUF, stdin);
if
(!strncasecmp(buf,
"no"
, 2)) {
printf
(
"终止聊天!\n"
);
break
;
}
}
close(sockfd);
return
0;
}
|
客户端源代码如下:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#define MAXBUF 1024
/************关于本文档********************************************
// *filename: ssync-client.c
*purpose: 演示网络异步通讯,这是客户端程序
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com
)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-25 21:32
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to: Google.com
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int
main(
int
argc,
char
**argv)
{
int
sockfd, len;
struct
sockaddr_in dest;
char
buffer[MAXBUF + 1];
fd_set rfds;
struct
timeval tv;
int
retval, maxfd = -1;
if
(argc != 3) {
printf
(
"参数格式错误!正确用法如下:\n\t\t%s IP地址 端口\n\t比如:\t%s 127.0.0.1 80\n此程序用来从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息"
,
argv[0], argv[0]);
exit
(0);
}
/* 创建一个 socket 用于 tcp 通信 */
if
((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror
(
"Socket"
);
exit
(
errno
);
}
/* 初始化服务器端(对方)的地址和端口信息 */
bzero(&dest,
sizeof
(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(
atoi
(argv[2]));
if
(inet_aton(argv[1], (
struct
in_addr *) &dest.sin_addr.s_addr) == 0) {
perror
(argv[1]);
exit
(
errno
);
}
/* 连接服务器 */
if
(connect(sockfd, (
struct
sockaddr *) &dest,
sizeof
(dest)) != 0) {
perror
(
"Connect "
);
exit
(
errno
);
}
printf
(
"\n准备就绪,可以开始聊天了……直接输入消息回车即可发信息给对方\n"
);
while
(1) {
/* 把集合清空 */
FD_ZERO(&rfds);
/* 把标准输入句柄0加入到集合中 */
FD_SET(0, &rfds);
maxfd = 0;
/* 把当前连接句柄sockfd加入到集合中 */
FD_SET(sockfd, &rfds);
if
(sockfd > maxfd)
maxfd = sockfd;
/* 设置最大等待时间 */
tv.tv_sec = 1;
tv.tv_usec = 0;
/* 开始等待 */
retval = select(maxfd + 1, &rfds, NULL, NULL, &tv);
if
(retval == -1) {
printf
(
"将退出,select出错! %s"
,
strerror
(
errno
));
break
;
}
else
if
(retval == 0) {
/* printf
("没有任何消息到来,用户也没有按键,继续等待……\n"); */
continue
;
}
else
{
if
(FD_ISSET(sockfd, &rfds)) {
/* 连接的socket上有消息到来则接收对方发过来的消息并显示 */
bzero(buffer, MAXBUF + 1);
/* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
len = recv(sockfd, buffer, MAXBUF, 0);
if
(len > 0)
printf
(
"接收消息成功:'%s',共%d个字节的数据\n"
,
buffer, len);
else
{
if
(len < 0)
printf
(
"消息接收失败!错误代码是%d,错误信息是'%s'\n"
,
errno
,
strerror
(
errno
));
else
printf
(
"对方退出了,聊天终止!\n"
);
break
;
}
}
if
(FD_ISSET(0, &rfds)) {
/* 用户按键了,则读取用户输入的内容发送出去 */
bzero(buffer, MAXBUF + 1);
fgets
(buffer, MAXBUF, stdin);
if
(!strncasecmp(buffer,
"quit"
, 4)) {
printf
(
"自己请求终止聊天!\n"
);
break
;
}
/* 发消息给服务器 */
len = send(sockfd, buffer,
strlen
(buffer) - 1, 0);
if
(len < 0) {
printf
(
"消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n"
,
buffer,
errno
,
strerror
(
errno
));
break
;
}
else
printf
(
"消息:%s\t发送成功,共发送了%d个字节!\n"
,
buffer, len);
}
}
}
/* 关闭连接 */
close(sockfd);
return
0;
}
|
编译用如下命令:
gcc -Wall async-server.c -o server
gcc -Wall async-client.c -o client
运行用如下命令:
./server 7838 1
./client 127.0.0.1 7838
相关推荐
Linux异步通信socket.
这是linux下实现的socket聊天室程序,可支持多线程多客户端的连接。使用时先运行服务器程序,再运行客户端,输入ip地址,即可连上。
linux-socket-select-异步聊天 linux-socket-select-异步聊天 linux-socket-select-异步聊天
基于linux下socket的聊天小程序
Winform Socket异步聊天程序,采用多线程技术,
linux C语言 socket通信聊天小程序
本实例包含: 1. C# SOCKET同步通讯实例的服务端和客户端端程序 2. C# SOCKET异步通讯实例的服务端和客户端端程序 需要用到胡知识点有:多线程 和 委托
基于socket异步通讯模式的代码,基于VC++ 可以实现socket异步通讯
zip包里有两个程序,一个server端一个client端,采用了微软建议的socket异步模式,先启动server程序,client端修改app.config serverhost value值,运行即可。
C# 使用Socket套接字、异步通讯,服务器端和客户端收发信息。
在别人程序基础上修改的基于TCP/IP的聊天程序,在传输文件功能上还有点问题
实现子进程的创建,用父子进进进行socket包的收发。调试到开发板上完全可以用。可以实现开发板和宿主机的socket通信。
暂时实现的功能有: 1.群聊 2.私聊 3.登陆验证 4.注册 5.所用的在线用户 6.退出 7.管理员踢出某用户 ...8.管理员禁止某用户聊天 9.管理员提升某用户为管理员 10.管理员把某用户降为普通用户
C# Socket异步聊天例,相关介绍参见我的博客
SilverLight Socket 异步通讯实例 可发送指令 控制服务器或客户端电脑做物理操作
基于linux的socket多人聊天室程序,采用posix多线程控制技术。客户端和服务器采用协议机制通信,服务器端在用户上线和下线时及时更新在线人数,并打印上下线信息(用户名)。客户端登陆需要输入用户名,若用户名已...
socket异步开发实例,用异步编写的socket通讯助手
实现socket简易的聊天程序,实现socket简易的聊天程序
Linux下用Socket和多线程实现简单聊天室
原创,Linux下Socket编程 聊天软件 暂不支持用户之间的私聊,改进中