socket服务器端编程的基本步骤:
domain--协议族,常用的有AF_INET(基于IPv4的Internet协议),AF_INET6(基于IPv6的Internet协议),AF_LOCAL(Unix本地通信协议)
type--传输类型,常用的有SOCK_STREAM(面向连接的可靠的带连接的传输方式,如TCP)、SOCK_DGRAM(面向消息的不可靠的无连接的传输方式,如UDP)
protocol--指定协议,在前面两个参数确定的情况下,若存在多种协议满足条件,用来指定某个协议,通常为0
返回值--socket文件操作符
sockfd--服务器的socket操作符
addr--储存地址信息的结构体
addrlen--储存地址信息的结构体的长度
返回值--成功返回0,失败返回-1
sockfd--服务器端的socket操作符
backlog--可保持的最大连接数
返回值--成功返回0,失败返回-1
int accept(int sockfd,struct sockaddr* addr,socklen_t* addrlen);
sockfd--服务器的socket操作符
addr--用来保存客户端地址信息的结构体
addrlen--客户端地址信息结构体的长度
fd--客户端的socket操作符
buf--要写入的字符序列
count--写入的序列的长度
返回值--返回实际写入的长度
sockfd--socket标识符
1.1 创建套接字
int socket(int domain,int type,int protocol);domain--协议族,常用的有AF_INET(基于IPv4的Internet协议),AF_INET6(基于IPv6的Internet协议),AF_LOCAL(Unix本地通信协议)
type--传输类型,常用的有SOCK_STREAM(面向连接的可靠的带连接的传输方式,如TCP)、SOCK_DGRAM(面向消息的不可靠的无连接的传输方式,如UDP)
protocol--指定协议,在前面两个参数确定的情况下,若存在多种协议满足条件,用来指定某个协议,通常为0
返回值--socket文件操作符
1.2 绑定地址信息
int bind(int sockfd,const struct sockaddr* addr,socklen_t* addrlen);sockfd--服务器的socket操作符
addr--储存地址信息的结构体
addrlen--储存地址信息的结构体的长度
返回值--成功返回0,失败返回-1
1.3 开启监听
int listen(int sockfd,int backlog);sockfd--服务器端的socket操作符
backlog--可保持的最大连接数
返回值--成功返回0,失败返回-1
1.4 接收连接
该函数为阻塞函数,直到接收到客户端的链接后退出阻塞状态int accept(int sockfd,struct sockaddr* addr,socklen_t* addrlen);
sockfd--服务器的socket操作符
addr--用来保存客户端地址信息的结构体
addrlen--客户端地址信息结构体的长度
1.5 向客户端socket写数据
ssize_t write(int fd,void* buf,size_t count);fd--客户端的socket操作符
buf--要写入的字符序列
count--写入的序列的长度
返回值--返回实际写入的长度
1.6 关闭套接字
close(int sockfd)sockfd--socket标识符
示例代码serv.c:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
void error_handling(char* message);
int main(int argc,char *argv[])
{
int serv_sock;
int clnt_sock;
struct sockaddr_in serv_addr;
struct sockaddr_in clnt_addr;
socklen_t clnt_addr_size;
char message[]="hello world!";
if(argc!=2)
{
printf("Usage : %s <port>\n",argv[0]);
exit(1);
}
serv_sock=socket(PF_INET,SOCK_STREAM,0);//创建socket
if(serv_sock==-1)
error_handling("sock error");
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_addr.sin_port=htons(atoi(argv[1]));
//绑定地址信息
if(bind(serv_sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1)
error_handling("bind error");
if(listen(serv_sock,5)==-1)//开启监听
error_handling("listen error");
clnt_addr_size=sizeof(clnt_addr);
//接受链接请求
clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_addr,&clnt_addr_size);
if(clnt_sock==-1)
error_handling("accept error");
write(clnt_sock,message,sizeof(message));
close(clnt_sock);
close(serv_sock);
return 0;
}
void error_handling(char* message)
{
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
Github位置:
https://github.com/HymanLiuTS/NetDevelopment
克隆本项目:
git clone git@github.com:HymanLiuTS/NetDevelopment.git
获取本文源代码:
git checkout NL01