前言
Socket编程是网络编程中至关重要的一部分,它提供了一种在不同主机之间进行数据通信的方式。
一、什么是socket网络编程?
百度:
套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。
其实socket就是一种通讯机制,通过它可以在不同主机之间交换数据,也可以理解为socket就是TCP协议的具体实现。
二、socket编程基本步骤
1.创建套接字
函数的功能:
创建套接字
函数的头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数的原型:
int socket(int domain, int type, int protocol);
函数的参数:
int domain: IP的类型
AF_INET: IPv4
AF_INET6: IPv6
int type:
SOCK_STREAM: 流式套接字 tcp
SOCK_DGRAM: 数据报 udp
int protocol: 0
函数的返回值:
成功返回: 套接字
失败返回: -1
2.绑定IP和端口
函数的功能:
绑定ip地址和端口
函数的头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数的原型:
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
函数的参数:
int sockfd: 套接字
const struct sockaddr *addr: IP地址端口结构体
socklen_t addrlen:结构体的长度
函数的返回值:
成功返回: 0
失败返回: -1
++++++++++++++++++++++++++++++++++++++++++++++++++
struct sockaddr
{
sa_family_t sa_family:IP地址的类型,AF_INET
char sa_data[14]:ip地址和端口号,拼接在一起的一个串
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
struct sockaddr_in
{
sa_family_t sin_family:AF_INET
in_port_t sin_port:端口号
struct in_addr sin_addr:ip地址
};
3.监听
函数的功能:
监听网络
函数的头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数的原型:
int listen(int sockfd, int backlog);
函数的参数:
int sockfd: 服务端的套接字
int backlog: 最大的客户端的链接的数目 最大是128
函数的返回值:
成功返回: 0
失败返回: -1
4.接受客户端的连接
函数的功能:
接受客户端的链接请求
函数的头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数的原型:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
函数的参数:
int sockfd: 服务端的套接字
struct sockaddr *addr: 存放客户端的ip端口信息
socklen_t *addrlen: 结构体的长度
函数的返回值:
成功返回: 新的套接字 专门用来跟客户端通讯
5.代码实现
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
int sd;
struct sockaddr_in seraddr;
struct sockaddr_in cliaddr;
int main(int argc, char *argv[])
{
//创建服务端套接字
sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0)
{
perror("socket");
return -1;
}
//绑定ip地址和端口
int ret = 0;
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(8888);//端口号
seraddr.sin_addr.s_addr = inet_addr("192.168.56.128");//服务器端IP地址
ret = bind(sd, (struct sockaddr *)&seraddr, sizeof(seraddr));
if (ret < 0)
{
perror("bind");
return -1;
}
int rt = 0;
//监听
rt = listen(sd, 10);
if (rt < 0)
{
perror("listen");
return -1;
}
//接受客户端链接
int clid = 0;
socklen_t cliaddrlen = sizeof(cliaddr);
clid = accept(sd, (struct sockaddr *)&cliaddr, &cliaddrlen);
if (clid < 0)
{
perror("accept");
return -1;
}
printf("新客户端已上线\n");
printf("新客户端IP:%s\n",inet_ntoa(cliaddr.sin_addr));
char buf[64]={0};
recv(clid,buf,64,0);
printf("接收客户端信息:%s\n",buf);
send(clid,"how are you?",sizeof("how are you?"),0);
printf("向客户端发送信息:%s\n","how are you?");
return 0;
}
实验现象: