对于linux下c语言的编程,尤其是网络编程这部分,还是有一些莫名的爱好的。学习了一些东西,如果不加以总结和实际操作,往往容易忘了。所以,在此写个系列的博客,记录一下,从零开始写linux下的服务器编程。希望看到这篇日志的同学,多提意见,共同学习。
对于网络编程,主要是对socket和IO进行操作。为了实现高效通讯,需要一些策略,后面会介绍到。作为开篇,主要是对socket的基础操作的讲解。
socket本质上就是一个int的数字,文件描述符,用于标识主机间端到端的通讯。两端的主机,通过对该socket进行读写,完成双方的通讯。
socket需要新建(socket())、绑定(bind()),监听(listen),接收连接(accept()),以及读写(read() write(),还有别的IO函数)等。绑定,是将已经新建好的socket与本地的地址进行一个联系。地址( struct sockaddr_in )的设定往往根据需要的具体情况,包括协议、端口、IP地址等。监听是告诉客户端,服务器这边已经准备好了,等待为其服务啦。接受连接是在客户端请求连接时,双方建立连接的通道,为通讯做好准备。接下来,就是数据交换(读和写)。关于读写的函数,比较多,read()\write(), recv()\send()、recvfrom\sendto(),recvmsg()\sendmsg()等。几组函数间比较相似,个别又有特点,接下来会有一篇专门介绍各种读写函数的。
学习的过程,更多的还是在于动手写。下面先写一个简单的demo,一个回射服务器(就是客户端传来什么内容,服务器就写回给客户端什么内容)。接下来的几个例子,都是在此基础上进行改进的。当然了,后面随着深入,简单的回射服务器可能不能满足我们的要求了,我们会写个http服务器之类的。下面是代码。具体的代码可以见托管处 http://git.oschina.net/mengqingxi89/codelittle/blob/master/codes/echoserver/echoser.cpp。当然了,这个demo是最基本的demo,只能处理一个客户的请求,异常处理什么的也没考虑。不过,接下来,我们会慢慢的优化,不要着急哦。
#include"head.h"
/*因为涉及的头文件比较多,单写了一个头文件,包括引用头文件和全局变量、常用函数的定义等*/
int main(int argc, char **argv)
{
if(argc<3)
{
printf("usage: %s ip port\n",basename(argv[0]));
exit(0);
}
printf("start echoback server...\n");
char * ip=(char * ) argv[1];
int port =atoi(argv[2]);
/*构造服务器端的地址,主要是填充sockaddr_in 结构体*/
struct sockaddr_in server_address;
bzero(&server_address,sizeof(server_address));
server_address.sin_family=AF_INET;
inet_pton(AF_INET,ip,&server_address.sin_addr);
server_address.sin_port=htons(port);
int listenfd=socket(AF_INET,SOCK_STREAM,0);
assert(listenfd>=0);
setnonblock(listenfd);
int ret=bind(listenfd,(struct sockaddr *) &server_address, sizeof(server_address));
assert(ret==0);
ret=listen(listenfd,5);
assert(ret==0);
/*服务器服务启动,等待客户端的链接的到来*/
int run_flag=1;
char buf[1024];
int conn=-1;
while(run_flag)
{
int acfd=accept(listenfd,NULL,NULL);
/*因为listenfd是非阻塞的,所以,可能返回是小于0的值,此时应该继续处理上一个连接*/
if(acfd>=0)
conn=acfd;
printf("%d\n",conn);
bzero(buf,1024);
int ret=read(conn,buf,1023);
if(ret>0)
{
buf[ret]=0;
printf("received: %s\n",buf);
write(conn,buf,ret);
}
else if (ret==0)
{
printf("read 0\n");
close(conn);
}
else
{
printf("read error\n");
close(conn);
}
}
}
在服务器端执行该文件,然后另起一个终端,用telnet连接对应的IP和PORT,就可以实现服务器与客户端的通讯了。
来源:oschina
链接:https://my.oschina.net/u/151387/blog/169501