这篇文章介绍一个最简单的网络程序,C/S模式,一个服务端进程只能为一个客户端进程服务。最早的计算机是为了应用大规模的计算而研发的,随着http协议以及网络技术的发展,网络通信在计算机的普及中起了非常大的作用,下面就列出了一个最简单的ECHO服务器的程序。
#include <netinet/in.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main()
{
struct sockaddr_in sockaddr;
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(40714);
sockaddr.sin_addr.s_addr = INADDR_ANY;
int clientfd;
int listenfd = socket(AF_INET, SOCK_STREAM, 0); //创建一个socket
if(bind(listenfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0)
{
perror("bind error");
return -1;
}
listen(listenfd, 16);
struct sockaddr_in clientAdd;
char buff[101] = {0};
socklen_t len = sizeof(clientAdd);
int closing =0;
clientfd = accept(listenfd, (struct sockaddr *)&clientAdd, &len);
int n;
while((n = recv(clientfd,buff, 100,0 )) > 0)
{
printf("number of receive bytes = %d\n", n);
//发送数据
send(clientfd, buff, n, 0);
char* bufTmp = buff;
while(*bufTmp != '\r' && *bufTmp !='\n')
bufTmp++;
*bufTmp = '\0';
if(strcmp(buff, "quit") == 0)
{
break;
}
}
close(clientfd);
close(listenfd);
return 0;
}
首先创建一个监听套接字,listenfd,并将该套接字绑定在回环地址以及端口40714上,然后启动监听,等待服务器发起连接请求,该过程accept函数会一直阻塞直到有客户端向该套接字发起连接请求,accpet函数才返回。
while循环用于等待客户端发送数据,并将客户端发送的数据发送回客户端,在该过程中,若客户端没发送数据或者内核未将数据准备好,recv调用将一直阻塞,直到内核将数据准备好后返回接受到的数据字节数,当接收到数据为0时说明客户端终止。
close()调用将关闭套接字相关的内容,由于在linux中套接字相当于文件描述符,系统为维护该套接字会分配一些内存,因此在使用完套接字后应该关闭套接字,以免占用系统资源。
测试:
由于该服务端程序是一个最简单的ECHO服务器,因此不必要专门写客户端代码来与服务端程序进行通信,为测试该代码,仅需要 telnet localhost 40714 或者 T telnet 127.0.0.1 40714,利用telnet向服务端发起连接。然后就可以向服务发送数据包,服务端会将你发送的内容回复给你。
在测试过程中,加入你再次向服务端发起连接请求并且发送数据,你会发现,你发送的数据得不到服务器的相应,这是因为当前服务端只能服务一个客户端的请求,后面来的请求都得不到服务端的处理,因此这就是这种最简单方式实现的弊端,当前的网络环境复杂务必,服务端可能同时接收到几千上万甚至上千万的并发连接,那么当前这种架构是无法处理这种大并发的。
那么要想服务端能够同时处理若干个客户端的请求该怎么办呢?请看下回分解。