[root@localhost chapter15]# cat server1.c
/* Make the necessary includes and set up the variables. */
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_un server_address;
struct sockaddr_un client_address;
/* Remove any old socket and create an unnamed socket for the server. */
unlink("server_socket");
server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
/* Name the socket. */
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, "server_socket"); //socket name is "server_socket"
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
/* Create a connection queue and wait for clients. */
printf("1\n");
listen(server_sockfd, 2);
printf("2\n");
while(1) {
char ch;
printf("3\n");
printf("server waiting\n");
/* Accept a connection. */
client_len = sizeof(client_address);
//sleep(30);
client_sockfd = accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);//may block
printf("4\n");
/* We can now read/write to client on client_sockfd. */
//sleep(3);
printf("before server read\n");
read(client_sockfd, &ch, 1);
printf("after server read\n");
ch++;
printf("before server write\n");
write(client_sockfd, &ch, 1);
printf("after server write\n");
close(client_sockfd);
}
}
[root@localhost chapter15]#
[root@localhost chapter15]# cat client1.c
/* Make the necessary includes and set up the variables. */
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int sockfd;
int len;
struct sockaddr_un address;
int result;
char ch = 'A';
/* Create a socket for the client. */
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
/* Name the socket, as agreed with the server. */
address.sun_family = AF_UNIX;
strcpy(address.sun_path, "server_socket");
//server name is "server_socket",the same as in server.c
len = sizeof(address);
/* Now connect our socket to the server's socket. */
result = connect(sockfd, (struct sockaddr *)&address, len); //当服务器队列满时,将会阻塞在此
if(result == -1) {
perror("oops: client1");
exit(1);
}
/* We can now read/write via sockfd. */
printf("before client write\n");
write(sockfd, &ch, 1);
printf("after client write\n");
printf("before client read\n");
read(sockfd, &ch, 1);
printf("after client read\n");
printf("char from server = %c\n", ch);
close(sockfd);
exit(0);
}
[root@localhost chapter15]#
[root@localhost chapter15]# ./server1&
[3] 11579
[root@localhost chapter15]# 1
2
3
server waiting
./client1
4
before server read
before client write
after server read
before server write
after server write
3
server waiting
after client write
before client read
after client read
char from server = B
服务器执行 bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
时,会在当前目录下创建一个socket文件
srwxr-xr-x. 1 root root 0 Aug 28 12:18 server_socket
而 listen(server_sockfd, 2);
只不过是创建一个可以容纳2个请求者的监听队列,并不是执行监听
监听并且接受连接的任务落在accept身上
client_sockfd = accept(server_sockfd,(struct sockaddr *)&client_address, &client_len);
当没有客户端连接请求时,服务器会阻塞在accept处
当有连接请求是,accept会创建一个与原有的命名套接字不同的新套接字,无名,这个
新套接字只用于与这个特定的客户进行通信
而原有的命名套接字则被保留下来继续处理来自其他客户的连接
也可看出,
服务器端read若执行在在客户端write之前,则服务器自动阻塞
客户端read若执行在服务器端write之前,则客户自动阻塞
即read必须在对方write之后才能顺利返回,否则阻塞
他们就是这样一唱一和勾结而同步操作的。
服务器运行在后台while,若多个client一起来临,则按照先后顺序被装进请求队列
服务器每一个while从队列里面仅拎出一个client处理掉
...
由于队列的存在,使得多个请求可以同时请求成功,即多个客户connect均可立即响应而不会阻塞,从而每个client只要连接上立即就能writer socket
但即使这样,由于服务器进程只有一个,也只能一个一个的从队列里面拿出socket处理,
如果某个socket的数据量很大,就需要不少时间,则后面排队的client就会抱怨怎么我的请求还没有处理哪
这样可以为每个连接创建一个线程/进程去执行之。