概述
文章目录
- socket介绍
- 网络通讯流程
- 函数原型
- socket
- connect
- bind
- listen
- accept
- 示例代码
- 服务端
- 客户端
socket介绍
socket,又叫做套接字,是对通讯双方中端点的抽象。在unix中,本着“一切皆文件”的原则,所以我们可以认为socket是一个为了完成当前任务而所创建的一个特殊文件,而网络通讯之间都通过这个socket来完成达到发送/接受数据的目的。
网络通讯流程
- 首先,服务端要先创建一个socket,称为监听套接字,然后对所需要进行监听的ip和端口进行绑定(ip可以理解为地址,端口是人名,因为服务端可以一个ip对应多个不同端口),然后开始进行监听客户端的请求,进入accpet阻塞
- 客户端创建一个套接字,通过套接字绑定所要访问的服务端的ip和端口,然后进行尝试进行connect连接,然后服务端的accpet阻塞就收到了来自客户端的请求,accpet返回的结果是一个新的套接字,称为连接套接字
- 此时已经建立好了客户端和服务端之间的通讯,两者通过连接套接字来进行数据的接受与发送
函数原型
socket
创建套接字,指定期望的通讯协议类型
#include<sys/socket.h>
int socket(int family,int type,int protocl);
family
指定协议族
AF_INET:IPv4
AF_INET6:IPv6协议
type
套接字类型
SOCK_STREAM:字节流套接字
SOCK_DGRAM:数据报套接字
SOCK_SEQPACKET:有序分组套接字
SOCK_RAW:原始套接字
protocol
某个协议类型常值或者为0
返回值
把套接字看为一个特殊文件,那么其实返回的就是一个套接字的文件描述符(整型),0、1、2分别为标准输入、标准输出、标准错误的文件描述符,所以成功创建的话返回值会大于2,返回-1说明出错
connect
客户端通过connect函数建立与服务端的连接
#include<sys/socket.h>
int connect(int sockfd,const struct sockaddr * servaddr,socklen_t addrlen)
sockfd
这个就是socket()函数返回的文件描述符
sockaddr
指向套接字地址结构的指针
addrlen
sockaddr指针指向的套接字结构的大小
返回值
成功的话返回0,出错返回-1
bind
服务端把一个本地协议地址赋予一个套接字
#include<sys/socket.h>
int bind(int sockfd,const struct sockaddr * myaddr,socklen_t addrlen)
sockfd
这个就是socket()函数返回的文件描述符
myaddr
指向套接字地址结构的指针
addrlen
myaddr指针指向的套接字结构的大小
返回值
成功的话返回0,出错返回-1
listen
服务器调用,
(1)其实通过socket()函数创建的套接字,会被假设为一个主动套接字,即默认这个套接字是后面要用connect()函数发起连接的客户端套接字,而listen就是将这个主动套接字转换为一个被动套接字,即告诉内核应该接受指向这个套接字的连接请求
(2)第二个参数规定了内核应该为相应套接字排队的最大连接个数
#include<sys/socket.h>
int listen(int sockfd,int backlog)
sockfd
这个就是socket()函数返回的文件描述符
backlog
内核应该为相应套接字排队的最大连接个数
返回值
0为成功,-1为失败
accept
服务端通过accept接收listen中监听到的来自客户端的请求
#include<sys/socket.h>
#include<arpa/inet.h>
int accpet(int sockfd,struct sockaddr * cliaddr,socklen_t *addrlen)
sockfd
这个就是socket()函数返回的文件描述符
cliaddr
指向对端进程(客户端)套接字地址结构的指针
addrlen
myaddr指针指向对端进程(客户端)的套接字结构的大小
返回值
成功的话,返回的是一个全新的套接字文件描述符,表示服务端与客户端之间的连接,失败返回-1.这个返回值称为连接套接字,socket()函数的返回值称为监听套接字
示例代码
下面代码简单实现了客户端和服务端的通讯,客户端发送消息给服务端,服务端收到消息后输出,然后发送给客户端…
服务端
#include<stdio.h>
#include<string.h>
#include<stdlib.h>// exit
#include<unistd.h> // read write close
#include<sys/socket.h>
#include<arpa/inet.h>// sockaddr_in
char buff[55];
int main(){
//1.创建socket,返回监听套接字
int listen_fd=socket(AF_INET,SOCK_STREAM,0);
if(listen_fd==-1){
printf("socket errorn");
exit(0);
}
printf("1.服务端创建套接字成功n");
//2.将服务端的通信类型,通信的ip和端口绑定到监听套接字上
struct sockaddr_in server_addr;
bzero(&server_addr,sizeof (server_addr));//清空
server_addr.sin_family=AF_INET;//协议IPV4
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);//任意IP
server_addr.sin_port=htons(5010);//端口为5010
if(bind(listen_fd,(struct sockaddr *)&server_addr,sizeof (server_addr))==-1){
printf("bind errorn");
close(listen_fd);
exit(0);
}
printf("2.服务端绑定套接字成功n");
//3.对套接字进行监听
if(listen(listen_fd,20)!=0){
printf("listen errorn");
close(listen_fd);
exit(0);
}
printf("3.服务端监听套接字成功n");
struct sockaddr_in client_addr;
socklen_t socklen=sizeof(sockaddr_in);
//4.accpet阻塞 得到连接套接字
int connect_fd=accept(listen_fd,(struct sockaddr *)&client_addr,&socklen);
if(connect_fd==-1){
printf("accept errorn");
close(listen_fd);
exit(0);
}
printf("4.服务端收到来自客户端的连接请求!!!!!!!!!!!!!!!!!!!n");
while(1){
memset(buff,0,sizeof (buff));
int n=read(connect_fd,buff,50);
if(n<0){
printf("read errorn");
close(listen_fd);
close(connect_fd);
exit(0);
}
printf("服务端收到了来自客户端的信息:n%sn",buff);
printf("下面请输入要发送给客户端的消息n");
memset(buff,0,sizeof (buff));
scanf("%s",buff);
n=write(connect_fd,buff,strlen(buff));
if(n<0){
printf("write errorn");
close(listen_fd);
close(connect_fd);
exit(0);
}
printf("服务端消息成功发送n");
}
close(connect_fd);
close(listen_fd);
return 0;
}
客户端
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>
#include<arpa/inet.h>
char buff[55];
int main(){
//1 创建套接字
int sock_fd=socket(AF_INET,SOCK_STREAM,0);
if(sock_fd==-1){
printf("socket errorn");
exit(0);
}
printf("1.客户端创建套接字成功n");
struct sockaddr_in clinent_addr;
bzero(&clinent_addr,sizeof (clinent_addr));// 清空
clinent_addr.sin_family=AF_INET;// 协议
clinent_addr.sin_addr.s_addr=htonl(INADDR_ANY); // ip
clinent_addr.sin_port=htons(5010);// 端口
if(connect(sock_fd, (struct sockaddr *)&clinent_addr, sizeof(clinent_addr)) != 0) // 向服务端发起连接清求。
{ printf("connect errorn");
close(sock_fd);
return -1;
}
printf("2.客户端连接到服务端成功!!!!!!!!!!!!!!!!n");
for(;;){
printf("下面请输入要发送给服务端的消息n");
memset(buff,0,sizeof (buff));
scanf("%s",buff);
int n=write(sock_fd,buff,strlen(buff));
if(n<0){
printf("write errorn");
exit(0);
}
printf("客户端消息成功发送n");
memset(buff,0,sizeof (buff));
n=read(sock_fd,buff,50);
if(n<0){
printf("read errorn");
close(sock_fd);
exit(0);
}
printf("收到了来自服务端的信息:n%sn",buff);
}
close(sock_fd);
return 0;
}
最后
以上就是糟糕心锁为你收集整理的socket编程初步socket介绍网络通讯流程函数原型示例代码的全部内容,希望文章能够帮你解决socket编程初步socket介绍网络通讯流程函数原型示例代码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复