socket编程的同步、异步与阻塞、非阻塞示例详解之二
来源:互联网 发布:mac怎么免费翻墙 编辑:程序博客网 时间:2024/05/23 01:56
接上文:
http://blog.chinaunix.net/uid-26000296-id-3755264.html
三、异步阻塞模式
另外一个阻塞解决方案是带有阻塞通知的非阻塞 I/O。
在这种模型中,配置的是非阻塞 I/O,然后使用阻塞 select 系统调用来确定一个 I/O 描述符何时有操作。
使 select 调用非常有趣的是它可以用来为多个描述符提供通知,而不仅仅为一个描述符提供通知。
对于每个提示符来说,我们可以请求这个描述符可以写数据、有读数据可用以及是否发生错误的通知
下面的C语言实现的例子,它从网络上接受数据写入一个文件中:
/*
* \brief
* tcp client
*/
#define SERVPORT 8080
#define MAXDATASIZE 100
#define TFILE "data_from_socket.txt"
int main(int argc, char *argv[])
{
int sockfd, recvbytes;
char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello */
char snd_buf[MAXDATASIZE];
struct hostent *host; /* struct hostent
* {
* char *h_name; // general hostname
* char **h_aliases; // hostname's alias
* int h_addrtype; // AF_INET
* int h_length;
* char **h_addr_list;
* };
*/
struct sockaddr_in server_addr;
/* */
fd_set readset, writeset;
int check_timeval = 1;
struct timeval timeout={check_timeval,0}; //阻塞式select, 等待1秒,1秒轮询
int maxfd;
int fp;
int cir_count = 0;
int ret;
if (argc < 3)
{
printf("Usage:%s [ip address] [any string]\n", argv[0]);
return 1;
}
*snd_buf = '\0';
strcat(snd_buf, argv[2]);
if ((fp = open(TFILE,O_WRONLY)) < 0) //不是用fopen
{
perror("fopen:");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket:");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVPORT);
inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
memset(&(server_addr.sin_zero), 0, 8);
/* create the connection by socket
* means that connect "sockfd" to "server_addr"
*/
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect");
exit(1);
}
/**/
if (send(sockfd, snd_buf, sizeof(snd_buf), 0) == -1)
{
perror("send:");
exit(1);
}
printf("send:%s\n", snd_buf);
while (1)
{
FD_ZERO(&readset); //每次循环都要清空集合,否则不能检测描述符变化
FD_SET(sockfd, &readset); //添加描述符
FD_ZERO(&writeset);
FD_SET(fp, &writeset);
maxfd = sockfd > fp ? (sockfd+1) : (fp+1); //描述符最大值加1
ret = select(maxfd, &readset, NULL, NULL, NULL); // 阻塞模式
switch( ret)
{
case -1:
exit(-1);
break;
case 0:
break;
default:
if (FD_ISSET(sockfd, &readset)) //测试sock是否可读,即是否网络上有数据
{
recvbytes = recv(sockfd, rcv_buf, MAXDATASIZE, MSG_DONTWAIT);
rcv_buf[recvbytes] = '\0';
printf("recv:%s\n", rcv_buf);
if (FD_ISSET(fp, &writeset))
{
write(fp, rcv_buf, strlen(rcv_buf)); // 不是用fwrite
}
goto end;
}
}
cir_count++;
printf("CNT : %d \n",cir_count);
}
end:
close(fp);
close(sockfd);
return 0;
}
perl实现:
#! /usr/bin/perl
###############################################################################
# \File
# tcp_client.pl
# \Descript
# send message to server
###############################################################################
use IO::Socket;
use IO::Select;
#hash to install IP Port
%srv_info =(
#"srv_ip" => "61.184.93.197",
"srv_ip" => "192.168.1.73",
"srv_port"=> "8080",
);
my $srv_addr = $srv_info{"srv_ip"};
my $srv_port = $srv_info{"srv_port"};
my $sock = IO::Socket::INET->new(
PeerAddr => "$srv_addr",
PeerPort => "$srv_port",
Type => SOCK_STREAM,
Blocking => 1,
# Timeout => 5,
Proto => "tcp")
or die "Can not create socket connect. $@";
$sock->send("Hello server!\n", 0) or warn "send failed: $!, $@";
$sock->autoflush(1);
my $sel = IO::Select->new($sock);
while(my @ready = $sel->can_read)
{
foreach my $fh(@ready)
{
if($fh == $sock)
{
while()
{
print $_;
}
$sel->remove($fh);
close $fh;
}
}
}
$sock->close();
四、异步非阻塞模式
最后,异步非阻塞 I/O 模型是一种处理与 I/O 重叠(并行)进行的模型。
以read系统调用为例
steps:
a. 调用read;
b. read请求会立即返回,说明请求已经成功发起了。
c. 在后台完成读操作这段时间内,应用程序可以执行其他处理操作。
d. 当 read 的响应到达时,就会产生一个信号或执行一个基于线程的回调函数来完成这次 I/O 处理过程。
/*
* \brief
* tcp client
*/
#define SERVPORT 8080
#define MAXDATASIZE 100
#define TFILE "data_from_socket.txt"
int main(int argc, char *argv[])
{
int sockfd, recvbytes;
char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello */
char snd_buf[MAXDATASIZE];
struct hostent *host; /* struct hostent
* {
* char *h_name; // general hostname
* char **h_aliases; // hostname's alias
* int h_addrtype; // AF_INET
* int h_length;
* char **h_addr_list;
* };
*/
struct sockaddr_in server_addr;
/* */
fd_set readset, writeset;
int check_timeval = 1;
struct timeval timeout={check_timeval,0}; //阻塞式select, 等待1秒,1秒轮询
int maxfd;
int fp;
int cir_count = 0;
int ret;
if (argc < 3)
{
printf("Usage:%s [ip address] [any string]\n", argv[0]);
return 1;
}
*snd_buf = '\0';
strcat(snd_buf, argv[2]);
if ((fp = open(TFILE,O_WRONLY)) < 0) //不是用fopen
{
perror("fopen:");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket:");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVPORT);
inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
memset(&(server_addr.sin_zero), 0, 8);
/* create the connection by socket
* means that connect "sockfd" to "server_addr"
*/
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect");
exit(1);
}
/**/
if (send(sockfd, snd_buf, sizeof(snd_buf), 0) == -1)
{
perror("send:");
exit(1);
}
printf("send:%s\n", snd_buf);
while (1)
{
FD_ZERO(&readset); //每次循环都要清空集合,否则不能检测描述符变化
FD_SET(sockfd, &readset); //添加描述符
FD_ZERO(&writeset);
FD_SET(fp, &writeset);
maxfd = sockfd > fp ? (sockfd+1) : (fp+1); //描述符最大值加1
ret = select(maxfd, &readset, NULL, NULL, &timeout); // 非阻塞模式
switch( ret)
{
case -1:
exit(-1);
break;
case 0:
break;
default:
if (FD_ISSET(sockfd, &readset)) //测试sock是否可读,即是否网络上有数据
{
recvbytes = recv(sockfd, rcv_buf, MAXDATASIZE, MSG_DONTWAIT);
rcv_buf[recvbytes] = '\0';
printf("recv:%s\n", rcv_buf);
if (FD_ISSET(fp, &writeset))
{
write(fp, rcv_buf, strlen(rcv_buf)); // 不是用fwrite
}
goto end;
}
}
timeout.tv_sec = check_timeval; // 必须重新设置,因为超时时间到后会将其置零
cir_count++;
printf("CNT : %d \n",cir_count);
}
end:
close(fp);
close(sockfd);
return 0;
}
五、server端程序:
/*
* \brief
* tcp server
*/
#define SERVPORT 8080
#define BACKLOG 10 // max numbef of client connection
#define MAXDATASIZE 100
int main(char argc, char *argv[])
{
int sockfd, client_fd, addr_size, recvbytes;
char rcv_buf[MAXDATASIZE], snd_buf[MAXDATASIZE];
char* val;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int bReuseaddr = 1;
char IPdotdec[20];
/* create a new socket and regiter it to os .
* SOCK_STREAM means that supply tcp service,
* and must connect() before data transfort.
*/
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket:");
exit(1);
}
/* setting server's socket */
server_addr.sin_family = AF_INET; // IPv4 network protocol
server_addr.sin_port = htons(SERVPORT);
server_addr.sin_addr.s_addr = INADDR_ANY; // auto IP detect
memset(&(server_addr.sin_zero),0, 8);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&bReuseaddr, sizeof(int));
if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr))== -1)
{
perror("bind:");
exit(1);
}
/*
* watting for connection ,
* and server permit to recive the requestion from sockfd
*/
if (listen(sockfd, BACKLOG) == -1) // BACKLOG assign thd max number of connection
{
perror("listen:");
exit(1);
}
while(1)
{
addr_size = sizeof(struct sockaddr_in);
/*
* accept the sockfd's connection,
* return an new socket and assign far host to client_addr
*/
printf("watting for connect...\n");
if ((client_fd = accept(sockfd, (struct sockaddr *)&client_addr, &addr_size)) == -1)
{
/* Nonblocking mode */
perror("accept:");
continue;
}
/* network-digital to ip address */
inet_ntop(AF_INET, (void*)&client_addr, IPdotdec, 16);
printf("connetion from:%d : %s\n",client_addr.sin_addr, IPdotdec);
//if (!fork())
{
/* child process handle with the client connection */
/* recive the client's data by client_fd */
if ((recvbytes = recv(client_fd, rcv_buf, MAXDATASIZE, 0)) == -1)
{
perror("recv:");
exit(1);
}
rcv_buf[recvbytes]='\0';
printf("recv:%s\n", rcv_buf);
*snd_buf='\0';
strcat(snd_buf, "welcome");
sleep(3);
/* send the message to far-hosts by client_fd */
if (send(client_fd, snd_buf, strlen(snd_buf), 0) == -1)
{
perror("send:");
exit(1);
}
printf("send:%s\n", snd_buf);
close(client_fd);
//exit(1);
}
//close(client_fd);
}
return 0;
}
http://blog.chinaunix.net/uid-26000296-id-3755264.html
三、异步阻塞模式
另外一个阻塞解决方案是带有阻塞通知的非阻塞 I/O。
在这种模型中,配置的是非阻塞 I/O,然后使用阻塞 select 系统调用来确定一个 I/O 描述符何时有操作。
使 select 调用非常有趣的是它可以用来为多个描述符提供通知,而不仅仅为一个描述符提供通知。
对于每个提示符来说,我们可以请求这个描述符可以写数据、有读数据可用以及是否发生错误的通知
下面的C语言实现的例子,它从网络上接受数据写入一个文件中:
/*
* \brief
* tcp client
*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/socket.h>
- #include <sys/select.h>
- #include <sys/time.h>
- #include <netdb.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
#define MAXDATASIZE 100
#define TFILE "data_from_socket.txt"
int main(int argc, char *argv[])
{
int sockfd, recvbytes;
char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello */
char snd_buf[MAXDATASIZE];
struct hostent *host; /* struct hostent
* {
* char *h_name; // general hostname
* char **h_aliases; // hostname's alias
* int h_addrtype; // AF_INET
* int h_length;
* char **h_addr_list;
* };
*/
struct sockaddr_in server_addr;
/* */
fd_set readset, writeset;
int check_timeval = 1;
struct timeval timeout={check_timeval,0}; //阻塞式select, 等待1秒,1秒轮询
int maxfd;
int fp;
int cir_count = 0;
int ret;
if (argc < 3)
{
printf("Usage:%s [ip address] [any string]\n", argv[0]);
return 1;
}
*snd_buf = '\0';
strcat(snd_buf, argv[2]);
if ((fp = open(TFILE,O_WRONLY)) < 0) //不是用fopen
{
perror("fopen:");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket:");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVPORT);
inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
memset(&(server_addr.sin_zero), 0, 8);
/* create the connection by socket
* means that connect "sockfd" to "server_addr"
*/
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect");
exit(1);
}
/**/
if (send(sockfd, snd_buf, sizeof(snd_buf), 0) == -1)
{
perror("send:");
exit(1);
}
printf("send:%s\n", snd_buf);
while (1)
{
FD_ZERO(&readset); //每次循环都要清空集合,否则不能检测描述符变化
FD_SET(sockfd, &readset); //添加描述符
FD_ZERO(&writeset);
FD_SET(fp, &writeset);
maxfd = sockfd > fp ? (sockfd+1) : (fp+1); //描述符最大值加1
ret = select(maxfd, &readset, NULL, NULL, NULL); // 阻塞模式
switch( ret)
{
case -1:
exit(-1);
break;
case 0:
break;
default:
if (FD_ISSET(sockfd, &readset)) //测试sock是否可读,即是否网络上有数据
{
recvbytes = recv(sockfd, rcv_buf, MAXDATASIZE, MSG_DONTWAIT);
rcv_buf[recvbytes] = '\0';
printf("recv:%s\n", rcv_buf);
if (FD_ISSET(fp, &writeset))
{
write(fp, rcv_buf, strlen(rcv_buf)); // 不是用fwrite
}
goto end;
}
}
cir_count++;
printf("CNT : %d \n",cir_count);
}
end:
close(fp);
close(sockfd);
return 0;
}
perl实现:
#! /usr/bin/perl
###############################################################################
# \File
# tcp_client.pl
# \Descript
# send message to server
###############################################################################
use IO::Socket;
use IO::Select;
#hash to install IP Port
%srv_info =(
#"srv_ip" => "61.184.93.197",
"srv_ip" => "192.168.1.73",
"srv_port"=> "8080",
);
my $srv_addr = $srv_info{"srv_ip"};
my $srv_port = $srv_info{"srv_port"};
my $sock = IO::Socket::INET->new(
PeerAddr => "$srv_addr",
PeerPort => "$srv_port",
Type => SOCK_STREAM,
Blocking => 1,
# Timeout => 5,
Proto => "tcp")
or die "Can not create socket connect. $@";
$sock->send("Hello server!\n", 0) or warn "send failed: $!, $@";
$sock->autoflush(1);
my $sel = IO::Select->new($sock);
while(my @ready = $sel->can_read)
{
foreach my $fh(@ready)
{
if($fh == $sock)
{
while()
{
print $_;
}
$sel->remove($fh);
close $fh;
}
}
}
$sock->close();
四、异步非阻塞模式
最后,异步非阻塞 I/O 模型是一种处理与 I/O 重叠(并行)进行的模型。
以read系统调用为例
steps:
a. 调用read;
b. read请求会立即返回,说明请求已经成功发起了。
c. 在后台完成读操作这段时间内,应用程序可以执行其他处理操作。
d. 当 read 的响应到达时,就会产生一个信号或执行一个基于线程的回调函数来完成这次 I/O 处理过程。
/*
* \brief
* tcp client
*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/socket.h>
- #include <sys/select.h>
- #include <sys/time.h>
- #include <netdb.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
#define MAXDATASIZE 100
#define TFILE "data_from_socket.txt"
int main(int argc, char *argv[])
{
int sockfd, recvbytes;
char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello */
char snd_buf[MAXDATASIZE];
struct hostent *host; /* struct hostent
* {
* char *h_name; // general hostname
* char **h_aliases; // hostname's alias
* int h_addrtype; // AF_INET
* int h_length;
* char **h_addr_list;
* };
*/
struct sockaddr_in server_addr;
/* */
fd_set readset, writeset;
int check_timeval = 1;
struct timeval timeout={check_timeval,0}; //阻塞式select, 等待1秒,1秒轮询
int maxfd;
int fp;
int cir_count = 0;
int ret;
if (argc < 3)
{
printf("Usage:%s [ip address] [any string]\n", argv[0]);
return 1;
}
*snd_buf = '\0';
strcat(snd_buf, argv[2]);
if ((fp = open(TFILE,O_WRONLY)) < 0) //不是用fopen
{
perror("fopen:");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket:");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVPORT);
inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
memset(&(server_addr.sin_zero), 0, 8);
/* create the connection by socket
* means that connect "sockfd" to "server_addr"
*/
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect");
exit(1);
}
/**/
if (send(sockfd, snd_buf, sizeof(snd_buf), 0) == -1)
{
perror("send:");
exit(1);
}
printf("send:%s\n", snd_buf);
while (1)
{
FD_ZERO(&readset); //每次循环都要清空集合,否则不能检测描述符变化
FD_SET(sockfd, &readset); //添加描述符
FD_ZERO(&writeset);
FD_SET(fp, &writeset);
maxfd = sockfd > fp ? (sockfd+1) : (fp+1); //描述符最大值加1
ret = select(maxfd, &readset, NULL, NULL, &timeout); // 非阻塞模式
switch( ret)
{
case -1:
exit(-1);
break;
case 0:
break;
default:
if (FD_ISSET(sockfd, &readset)) //测试sock是否可读,即是否网络上有数据
{
recvbytes = recv(sockfd, rcv_buf, MAXDATASIZE, MSG_DONTWAIT);
rcv_buf[recvbytes] = '\0';
printf("recv:%s\n", rcv_buf);
if (FD_ISSET(fp, &writeset))
{
write(fp, rcv_buf, strlen(rcv_buf)); // 不是用fwrite
}
goto end;
}
}
timeout.tv_sec = check_timeval; // 必须重新设置,因为超时时间到后会将其置零
cir_count++;
printf("CNT : %d \n",cir_count);
}
end:
close(fp);
close(sockfd);
return 0;
}
五、server端程序:
/*
* \brief
* tcp server
*/
- #include <stdio.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <string.h>
- #include <stdlib.h>
#define BACKLOG 10 // max numbef of client connection
#define MAXDATASIZE 100
int main(char argc, char *argv[])
{
int sockfd, client_fd, addr_size, recvbytes;
char rcv_buf[MAXDATASIZE], snd_buf[MAXDATASIZE];
char* val;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int bReuseaddr = 1;
char IPdotdec[20];
/* create a new socket and regiter it to os .
* SOCK_STREAM means that supply tcp service,
* and must connect() before data transfort.
*/
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket:");
exit(1);
}
/* setting server's socket */
server_addr.sin_family = AF_INET; // IPv4 network protocol
server_addr.sin_port = htons(SERVPORT);
server_addr.sin_addr.s_addr = INADDR_ANY; // auto IP detect
memset(&(server_addr.sin_zero),0, 8);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&bReuseaddr, sizeof(int));
if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr))== -1)
{
perror("bind:");
exit(1);
}
/*
* watting for connection ,
* and server permit to recive the requestion from sockfd
*/
if (listen(sockfd, BACKLOG) == -1) // BACKLOG assign thd max number of connection
{
perror("listen:");
exit(1);
}
while(1)
{
addr_size = sizeof(struct sockaddr_in);
/*
* accept the sockfd's connection,
* return an new socket and assign far host to client_addr
*/
printf("watting for connect...\n");
if ((client_fd = accept(sockfd, (struct sockaddr *)&client_addr, &addr_size)) == -1)
{
/* Nonblocking mode */
perror("accept:");
continue;
}
/* network-digital to ip address */
inet_ntop(AF_INET, (void*)&client_addr, IPdotdec, 16);
printf("connetion from:%d : %s\n",client_addr.sin_addr, IPdotdec);
//if (!fork())
{
/* child process handle with the client connection */
/* recive the client's data by client_fd */
if ((recvbytes = recv(client_fd, rcv_buf, MAXDATASIZE, 0)) == -1)
{
perror("recv:");
exit(1);
}
rcv_buf[recvbytes]='\0';
printf("recv:%s\n", rcv_buf);
*snd_buf='\0';
strcat(snd_buf, "welcome");
sleep(3);
/* send the message to far-hosts by client_fd */
if (send(client_fd, snd_buf, strlen(snd_buf), 0) == -1)
{
perror("send:");
exit(1);
}
printf("send:%s\n", snd_buf);
close(client_fd);
//exit(1);
}
//close(client_fd);
}
return 0;
}
九四,或跃在渊,无咎。
【白话】九四,龙或腾跃而起,或退居于渊,均不会有危害。
《象》曰:“或跃在渊”,进无咎也。
【白话】《象辞》说:“龙或腾跃而起,或退居于渊,均不会有危害”,因为能审时度势,故进退自如,不会有危害。
0
上一篇:socket编程的同步、异步与阻塞、非阻塞示例详解之一
下一篇:socket简单应用服务端代码(原创)tcp c/s
相关热门文章
- c++ virtual析构函数详解...
- Linux设备驱动程序学习(5)-...
- Oracle:replace和translate函...
- 关于ORACLE COMMIT操作的详解...
- Linux逻辑卷详解总结
- SQL注入之asp+MSSQL
- 黑客高手讲述入侵的实践经验...
- "没有找到COMRes.dll,应用程...
- 如何给文件夹设置密码?...
- 详解zabbix安装部署(Server端...
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
0 0
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket网络编程之路 第六篇 -----同步与异步,阻塞与非阻塞的区别
- 网络编程之 Socket的模式(一) --- “阻塞/非阻塞” 与 “同步/异步”
- vim常用的命令,供备忘
- 如何下载db2的安装包/补丁包/介质/Fix Pack?
- 什么是互联网金融
- asterisk -r 出现Unable to connect to remote asterisk的解决方法
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- 别怕,手把手带你撕、拉、扯下SpringMVC的外衣
- socket简单应用服务端代码(原创)tcp c/s
- Linux文件权限
- 里氏七大原则
- Another MySQL daemon already running with the same unix socket
- SO_KEEPALIVE选项
- 查看程序线程数 文件打开数
- windows 7系统安装与配置Tomcat服务器环境
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
刀刨
厨房刨刀
刨笔刀
木工电动刨刀
剥皮刀
刨刀种类
刨刀怎么用
刨刀图片
刨刀轴
木工合金刨刀
木工刨床刨刀
削皮机
刨土
刨坑的拼音
刨坑
人生得意须尽欢 刨坑坑
刨子图片
木工刨子价格
木工电刨子电锯一体机
木工手工刨子
刨子版画锤
手提电刨子价格
电刨子电锯一体机
台式电锯电刨子一体机
木工电刨子
电刨子价格
木工刨子图片
木工刨子安装图解
木工刨子
大嘴刨幺
下载东北创幺
吉祥刨幺
东北刨幺手机版下载
下载刨幺
波克棋牌刨幺
风雷刨幺
qq东北刨幺算牌器
东北刨幺记牌器
qq东北刨幺记牌器
吉祥棋牌东北刨幺
浪人算牌之边锋刨幺