一.Linux C 网络编程知识介绍:
网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端.
客户端:(client)
在网络程序中,如果一个程序主动和外面的程序通信,那么我们把这个程序称为客户端程 序。比如我们使用ftp程序从另外一个地方获取文件的时候,是我们的ftp程序主动同外面进行通信(获取文件),所以这个地方我们的ftp程序就是客户端程序。
服务端:(server)
和客户端相对应的程序即为服务端程序。被动的等待外面的程序来和自己通讯的程序称为服务端程序。
比如上面的文件获取中,另外一个地方的程序就是服务端,我们从服务端获取文件过来。
互为客户和服务端
实际生活中有些程序是互为服务和客户端。在这种情况项目,一个程序既为客户端也是服务端。
TCP/UDP介绍
TCP(Transfer Control Protocol)传输控制协议是一种面向连接的协议, 当我们的网络程序使用这个协议的时候,网络可以保证我们的客户端和服务端的连接是可靠的,安全的.
UDP(User Datagram Protocol)用户数据报协议是一种非面向连接的协议, 这种协议并不能保证我们的网络程序的连接是可靠的,所以我们现在编写的程序一般是采用TCP协议的.
二.Socket编程-初等网络函数总结(TCP)
Linux系统是通过提供套接字(socket)来进行网络编程的.网络程序通过socket和其它几个函数的调用,会返回一个通讯的文件描述符,我们可以将这个描述符看成普通的文件的描述符来操作,这就是linux的设备无关性的好处. 我们可以通过向描述符读写操作实现网络之间的数据交流.
1.建立socket套接字(调用socket函数来创建一个能够进行网络通信的套接字)
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain,int type,int protocol);
参数domain指定通信协议簇,对于TCP/IP协议簇使用AF_INET.
参数 type 表示套接字类型 流类型SOCKET_STREAM(TCP) 数据报类型SOCKET_DGRAM(UDP)
原始套接字 SOCKET_RAW
创建示例:
struct protoent *ppe
ppe=getprotobyname("tcp");
int socketfd=socket(AF_INET,SOCKET_STREAM,ppe->p_proto);
2.使用bind()函数将一本地地址与一套接口捆绑
当用socket创建套接口后,它便存在于一个名字空间(地址族)中,但并未赋名。bind()函数通过给一个未命名套接口分配一个本地名字来为套接口建立本地捆绑(主机地址/端口号)。
#include<...省略>
int bind(int socketfd, struct sockaddr* myaddr, socklen_t addrlen)
参数一:建立的socket描述字
参数二:指向sockaddr结构体类型的指针
参数三:sockaddr的长度可使用sizeof(struct sockaddr)
绑定示例:
struct sockaddr_in my_addr;
int sockfd = socket(AF_INET,SOCK_STREAM,0);//创建基于流套接字
my_addr.sin_family = AF_INET;//IPv4协议族
my_addr.sin_port = htons(port);//端口转换
my_addr.sin_addr.s_addr = INADDR_ANY;// 表示服务器可以接收任意设备连接
bzero(&(my_addr.sin_zero),0);//初始化
if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(myaddr)) == -1)
{
perror("bind");
exit(1);
}
3.Listen()监听函数
作用:将一个套接字转换为倾听套接字(Listening socket).
int listen(int sockfd,int backlog);
sockfd:是bind后的文件描述符.
backlog:设置请求排队的最大长度.当有多个客户端程序和服务端相连时, 使用这个表示可以介绍的排队长度.
listen函数将bind的文件描述符变为监听套接字.返回的情况和bind一样.
函数socket创建的套接字是主动的套接字,可以用它来进行主动连接(用connect())但是不能接收请求...
服务器的套接字必须要被动接收来自客户机的请求,函数listen告诉TCP协议这个套接字可以接收连接请求
4.accept()函数
函数accept从倾听套接字中接收一个连接.如果完成连接队列为空,那么这个进程睡眠
int accept(int sockfd,struct sockaddr *addr ,int *addrlen);
返回一个新的套接字描述符.
示例:
if((clientfd = accept(sockfd,(struct sockaddr*)&their_addr,&sin_size)) == -1)
//接收客户端连接
{
perror("accept");
exit(1);
}
5.connect()
int connect(int sockfd, struct sockaddr * serv_addr,int addrlen);
/*sockfd:socket返回的文件描述符.
serv_addr:储存了服务器端的连接信息.其中sin_add是服务端的地址
addrlen:serv_addr的长度 */
用服务器端地址端口填充好serv_addr
connect函数是客户端用来同服务端连接的.成功时返回0,sockfd是同服务端通讯的文件描述符失败时返回-1.
6.close(sockfd);
7.read write
函数read write从套接字读和写数据.定义如下:
int read(int fd,char *buf,int len);
int write(int fd,char *buf,int len);