网络是用物理链路将各个孤立的工作站或主机相连在一起,组成数据链路,从而达到资源共享和通信的目的。
通信是人与人之间通过某种媒体进行的信息交流与传递。网络通信是通过网络将各个孤立的设备进行连接,通过信息交换实现人与人,人与计算机,计算机与计算机之间的通信。
网络通信中最重要的就是网络通信协议。当今网络协议有很多,局域网中最常用的有三个网络协议:MICROSOFT的NETBEUI、NOVELL的IPX/SPX和TCP/IP协议。应根据需要来选择合适的网络协议。
网络协议就是网络之间沟通、交流的桥梁,只有相同网络协议的计算机才能进行信息的沟通与交流。这就好比人与人之间交流所使用的各种语言一样,只有使用相同语言才能正常、顺网络通信利地进行交流。从专业角度定义,网络协议是计算机在网络中实现通信时必须遵守的约定,也就是通信协议。主要是对信息传输的速率、传输代码、代码结构、传输控制步骤、出错控制等作出规定并制定出标准。
C/C++的后台程序都需要进行网络通讯,其实现方法无非有两种:使用系统底层Socket或者使用已有的封装好的网络库(重量级的ACE,轻量级的有Libevent,Libev,libcurl,还有 Boost的ASIO)。
一. 系统底层的Socket编程
主要有以下6个步骤:
(1)socket()函数
(2)bind()函数
(3)listen()、connect()函数
(4)accept()函数
(5)read()、write()函数等
(6)close()函数
下面直接引用文章里的代码说明:
server端:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define MYPORT 3490 /*定义用户连接端口*/
#define BACKLOG 10 /*多少等待连接控制*/
main()
{
int sockfd, new_fd; /* listen on sock_fd, new connection on new_fd */
struct sockaddr_in my_addr; /* my address information */
struct sockaddr_in their_addr; /* connector's address information */
int sin_size;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
my_addr.sin_family = AF_INET; /* host byte order */
my_addr.sin_port = htons(MYPORT); /* short, network byte order */
my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */
bzero(&(my_addr.sin_zero),; /* zero the rest of the struct */
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))== -1)
{
perror("bind");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1)
{
perror("listen");
exit(1);
}
while(1)
{ /* main accept() loop */
sin_size = sizeof(struct sockaddr_in);
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
continue;
}
printf("server: got connection from %s\n", \
inet_ntoa(their_addr.sin_addr));
if (!fork()) { /* this is the child process */
if (send(new_fd, "Hello, world!\n", 14, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd); /* parent doesn't need this */
while(waitpid(-1,NULL,WNOHANG) > 0); /* clean up child processes */
}
}
client端:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define PORT 3490 /* 客户机连接远程主机的端口 */
#define MAXDATASIZE 100 /* 每次可以接收的最大字节 */
int main(int argc, char *argv[])
{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct hostent *he;
struct sockaddr_in their_addr; /* connector's address information */
if (argc != 2) {
fprintf(stderr,"usage: client hostname\n");
exit(1);
}
if ((he=gethostbyname(argv[1])) == NULL) { /* get the host info */
herror("gethostbyname");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
their_addr.sin_family = AF_INET; /* host byte order */
their_addr.sin_port = htons(PORT); /* short, network byte order */
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(their_addr.sin_zero),; /* zero the rest of the struct */
if(connect(sockfd,(struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1) {
perror("connect");
exit(1);
}
if ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("Received: %s",buf);
close(sockfd);
return 0;
}
二. 常用开源socket库
1. ACE
ACE是一个大型的中间件产品,代码20万行左右,过于宏大,一堆的设计模式,架构了一层又一层,使用的时候,要根据情况,看你从那一层来进行使用。支持跨平台。(详细资料可查看: http://www.cs.wustl.edu/~schmidt/ACE.html)
2. Boost的ASIO
Boost的ASIO是一个异步IO库,封装了对Socket的常用操作,简化了基于Socket程序的开发。它开源、免费、支持跨平台。(详细资料可查看:http://think-async.com/)
3. libevent
libevent是一个C语言写的网络库, 官方主要支持的是类linux操作系统, 最新的版本添加了对windows的IOCP的支持。由于IOCP是异步IO,与linux下的POLL模型,EPOLL模型,还有freebsd的KQUEUE等这些同步模型在用法上完全不一致,所以使用方法也不一样,就好比ACE中的Reactor和Proactor模式一样,使用起来需要转变思路。如果对性能没有特别的要求,那么使用libevent中的select模型来实现跨平台的操作, select模型可以横跨windows, linux, unix,solaris等系统。(详细资料可查看: http://libevent.org/)
4. libev
libev是一个C语言写的,它是一个C语言写的,只支持Linux系统的库,以前的时候只封装了EPOLL模型.使用方法类似libevent,但是非常简洁,代码量是最少的一个库,也就几千行代码。显然这样的代码跨平台肯定是无法支持的了,如果你只需要在Linux下面运行,那用这个库也是可以的。(详细资料可查看:http://software.schmorp.de/pkg/libev.html)
5. Linux Socket Programming In C++
详细资料可查看:http://tldp.org/LDP/LG/issue74/tougher.html)
6. C++ Sockets Library
它是一个跨平台的Sockets库,实现包括TCP、UDP、ICMP、SCTP协议。已实现的应用协议包括有SMTP、HTTP(S)、Ajp。具有SOCKS客户端实现以及匿名DNS,支持HTTP的GET/POST/PUT以及WebServer的框架。(详细参考资料可查看: http://www.alhem.net/Sockets/index.html)
7. Simple Socket
这个类库让编写基于Socket的客户/服务器程序更加容易。(详细资料可查看:http://home.kpn.nl/lcbokkers/simsock.htm)
8. POCO
POCO C++ Libraries提供一套C++的类库用以开发基于网络的可移植的应用程序,功能涉及线程、线程同步、文件系统访问、流操作、共享库和类加载、套接字以及网络协议包括:HTTP、FTP、SMTP等;其本身还包含一个HTTP服务器,提供XML的解析和SQL数据库的访问接口。POCO库的模块化、高效的设计及实现使得POCO特别适合嵌入式开发。在嵌入式开发领域,由于C++既适合底层(设备I/O、中断处理等)和高层面向对象开发,越来越流行。(详细资料可查看:http://pocoproject.org/)
9. Libcurl
免费的轻量级的客户端网络库,支持DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS,LDAP, LDAPS,POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet, TFTP.支持SSL, HTTPPOST,HTTPPUT, FTP上传, HTTP form上传,代理,cookies,用户名与密码认证。(详细资料可查看:http://curl.haxx.se/libcurl/)
10. libiop
一个c语言开发的跨平台网络IO库。功能特性:c/c++api,底层支持epoll,select,poll等io模型;异步事件模型;任务池模型,跨平台线程接口;跨平台(Linux/windows);日志服务;稳定,支持7*24小时无间断运行,自动处理异常状态;高并发与快速响应;API简洁,学习成本低。(详细资料可查看: http://sourceforge.net/projects/libiop/)
11.Muduo
muduo 是一个基于 Reactor 模式的现代 C++ 网络库,它采用非阻塞 IO 模型,基于事件驱动和回调,原生支持多核多线程,适合编写 Linux 服务端多线程网络应用程序。视频连接:http://v.youku.com/v_show/id_XNDIyNDc5MDMy.html,性能对比:http://www.oschina.net/p/muduo
使用 C++11 以及 Makefile 进行构建,详情请看https://github.com/AlexStocks/muduo