[b]不使用select
普通的基础socket连接,对多个客户端的反应
是有顺序的,根据建立连接的顺序[/b]
[color=red]
1.建立服务端socket
2.服务端socket准备建立新的connection,accept阻塞
3.客户端建立socket,
客户端connect 服务端
4.服务端accept返回,建立了一个connnection
并阻塞到recv,准备接受数据(几个客户端就会简历几个connection)
5.客户端向socket发送数据
6.服务端的connection 这时候recv收到数据并返回
[/color]
一言不合上代码,先用c写:
server.c
client.c
gcc server.c -o server
gcc client.c -o client
[b]测试server端:[/b]
[code="java"]
# ./server
======waiting for client's request======
[/code]
[b]开三个客户端观察[/b]
第一个
[code="java"]
# ./client 127.0.0.1
send msg to server:
[/code]
这里先不输入
-------------------------
第二个
[code="java"]
# ./client 127.0.0.1
send msg to server:
hello this is 2222222222222
回车
[/code]
观察server端没有反应
---------------------
第三个客户端:
[code="java"]
# ./client 127.0.0.1
send msg to server:
hello this is 33333333
回车
[/code]
观察server端没有反应
---------------
再到第一个客户端
[code="java"]
# ./client 127.0.0.1
send msg to server:
this is 111111111
[/code]
回车,
观察服务端
为
[code="java"]
# ./server
======waiting for client's request======
recv msg from client: hello this is 1111111111
recv msg from client: hello this is 2222222222222
recv msg from client: hello this is 33333333
[/code]
[b]发现,服务端返回的值是按照客户端打开connection的顺序返回的
说明给服务端建立连接后,就阻塞在recv上了
,即使后面的client先发送数据,也不会先返回[/b]
想哪个先发送就先返回需要使用select等
如果没有select等,
socket是阻塞的,
第一个客户端连接的时候就accept到那里等着了,只有第一个有反应了,后两个才会继续进行,
服务端返回的也是按连接建立的顺序返回的
再看socket的建立过程
一共四个过程,服务端阻塞两次,等待连接和接收消息
客户端建立连接和发送数据两次触发服务端
-------------(1)-------------
服务端:
server端先建立个socket句柄
listenfd = socket(AF_INET, SOCK_STREAM, 0)
绑定地址
bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)
监听socket
listen(listenfd, 10)
建立连接句柄,
并且阻塞##################
connfd =accept(listenfd, (struct sockaddr*)NULL, NULL)
注意
------------(2)---------
客户端:
建立socket句柄
sockfd = socket(AF_INET, SOCK_STREAM, 0)
用这个句柄连接到远程的地址
connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)
--------------(3)--------------
服务端accept的阻塞返回
n = recv(connfd, buff, MAXLINE, 0);
阻塞数据################
---------------(4)---
客户端
句柄发送数据
send(sockfd, sendline, strlen(sendline), 0)
----------------(5)--------------
服务端:
接受消息recv返回
######################################################
这样的普通socket会有顺序问题,
如果想,后面客户端先发送数据,server端不等待前面的客户端反应,就直接返回后面客户端的相应,
需要引入select等
参考[url]http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html[/url]
普通的基础socket连接,对多个客户端的反应
是有顺序的,根据建立连接的顺序[/b]
[color=red]
1.建立服务端socket
2.服务端socket准备建立新的connection,accept阻塞
3.客户端建立socket,
客户端connect 服务端
4.服务端accept返回,建立了一个connnection
并阻塞到recv,准备接受数据(几个客户端就会简历几个connection)
5.客户端向socket发送数据
6.服务端的connection 这时候recv收到数据并返回
[/color]
一言不合上代码,先用c写:
server.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#define MAXLINE 4096
int main(int argc, char** argv)
{
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[4096];
int n;
if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(6666);
if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}
if( listen(listenfd, 10) == -1){
printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}
printf("======waiting for client's request======\n");
while(1){
if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1){
printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
continue;
}
n = recv(connfd, buff, MAXLINE, 0);
buff[n] = '\0';
printf("recv msg from client: %s\n", buff);
close(connfd);
}
close(listenfd);
}
client.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#define MAXLINE 4096
int main(int argc, char** argv)
{
int sockfd, n;
char recvline[4096], sendline[4096];
struct sockaddr_in servaddr;
if( argc != 2){
printf("usage: ./client <ipaddress>\n");
exit(0);
}
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
exit(0);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(6666);
if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){
printf("inet_pton error for %s\n",argv[1]);
exit(0);
}
if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){
printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}
printf("send msg to server: \n");
fgets(sendline, 4096, stdin);
if( send(sockfd, sendline, strlen(sendline), 0) < 0)
{
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
close(sockfd);
exit(0);
}
gcc server.c -o server
gcc client.c -o client
[b]测试server端:[/b]
[code="java"]
# ./server
======waiting for client's request======
[/code]
[b]开三个客户端观察[/b]
第一个
[code="java"]
# ./client 127.0.0.1
send msg to server:
[/code]
这里先不输入
-------------------------
第二个
[code="java"]
# ./client 127.0.0.1
send msg to server:
hello this is 2222222222222
回车
[/code]
观察server端没有反应
---------------------
第三个客户端:
[code="java"]
# ./client 127.0.0.1
send msg to server:
hello this is 33333333
回车
[/code]
观察server端没有反应
---------------
再到第一个客户端
[code="java"]
# ./client 127.0.0.1
send msg to server:
this is 111111111
[/code]
回车,
观察服务端
为
[code="java"]
# ./server
======waiting for client's request======
recv msg from client: hello this is 1111111111
recv msg from client: hello this is 2222222222222
recv msg from client: hello this is 33333333
[/code]
[b]发现,服务端返回的值是按照客户端打开connection的顺序返回的
说明给服务端建立连接后,就阻塞在recv上了
,即使后面的client先发送数据,也不会先返回[/b]
想哪个先发送就先返回需要使用select等
如果没有select等,
socket是阻塞的,
第一个客户端连接的时候就accept到那里等着了,只有第一个有反应了,后两个才会继续进行,
服务端返回的也是按连接建立的顺序返回的
再看socket的建立过程
一共四个过程,服务端阻塞两次,等待连接和接收消息
客户端建立连接和发送数据两次触发服务端
-------------(1)-------------
服务端:
server端先建立个socket句柄
listenfd = socket(AF_INET, SOCK_STREAM, 0)
绑定地址
bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)
监听socket
listen(listenfd, 10)
建立连接句柄,
并且阻塞##################
connfd =accept(listenfd, (struct sockaddr*)NULL, NULL)
注意
------------(2)---------
客户端:
建立socket句柄
sockfd = socket(AF_INET, SOCK_STREAM, 0)
用这个句柄连接到远程的地址
connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)
--------------(3)--------------
服务端accept的阻塞返回
n = recv(connfd, buff, MAXLINE, 0);
阻塞数据################
---------------(4)---
客户端
句柄发送数据
send(sockfd, sendline, strlen(sendline), 0)
----------------(5)--------------
服务端:
接受消息recv返回
######################################################
这样的普通socket会有顺序问题,
如果想,后面客户端先发送数据,server端不等待前面的客户端反应,就直接返回后面客户端的相应,
需要引入select等
参考[url]http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html[/url]