套接字编程:套接字地址结构:
#include
struct sockaddr_in
{
unsigned short sin_family; //地址类型
unsigned short int sin_port; //端口号
struct in_addr sin_addr; //IP地址
unsigned char sin_zero[8]; //填充字节,一般赋值为0.
};
sin_family表示地址类型,对于使用TCP/IP协议进行的网络编程,该值只能是AF_INET。
数组sin_zero为填充字段,一般赋值为0
一下是设置地址信息的代码:
struct sockaddr_in sock;
sock.sin_family = AF_INET;
sock.si_port = htons(80); //设置端口号为80,端口为16位的整数
sock.sin_addr.s_addr = inet_addt("202.205.3.195"); //设置地址
menset(sock.sin_zero, 0, sizeof(sock.sin_zero)); //将数组sin_zero清0
创建套接字:
#include
#include
int socket(int domain, int type, int protocol);
参数domain用于指定创建套接字所使用的协议族,常用的协议族有:
1,AF_UNIX:创建只在本机内进行通信的套接字
2,AF_INET:使用IPv4 TCP/IP协议
3,AF_INET6:使用IPv6 TCP/IP协议
参数type指定套接字的类型
1,SOCK_STREAM:创建TCP流套接字
2,SOCK_DGRAM:创建UDP数据报套接字
3,SOCK_RAM:创建原始套接字
参数prorocol一般设定为0
下面的代码创建了一个TCP套接字:
int sock_fd;
sock_fd = socket (AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0)
{
perror("socket!\n");
exit(1);
}
建立连接:
函数connect用来在一个指定的套接字上创建一个连接:
#include
#include
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
参数sockfd是一个由函数socket创建的套接字,如果套接字的类型是SOCK_STREAM,则connect函数用于向服务器发出连接请求,服务器的IP地址和端口号由参数serv_addr指定。如果套接字的类型是SOCK_DGRAM,则connect函数并不建立连接,他只是告诉内核与该套接字进行通信的目的地址,只有该目的的地址发来的数据才会被该socket接受。
绑定套接字:
函数bind用来将一个套接字和某个端口绑定在一起。
#include
#include
int bind(int socket, struct sockaddr * my_addr, socklen_t addrlen);
socket函数只是创建了一个套接字,这个套接字将工作在那个端口上,程序并没有指定,前面提到,只有在客户机/服务器模型中,服务器端得IP地址和端口号一般是固定的,因此在服务器端得程序中,使用bind函数将一个套接字和某个端口绑定在一起
在套接字上监听:
函数listen把套接字转化成被动监听
#include
int listen (int s ,int backlog);
由函数socket创建的套接字是主动套接字,这种套接字可以用来主动请求连接到某个服务器(通过connect函数),但是作为服务器端得程序,通常在某个端口上监听等待来自客户的端的链接请求。
在服务器端通常是用socket创建一个主动套接字,然后调用函数bind将该套接字绑定到某个端口,接着再调用函数listen将该套接字转化为监听套接字,等待一个来自客户端的请求
接受连接:
函数accept用来接受一个连接请求
#include
#include
in accept (int s, struct sockadd * addr, socklen_t * addrlen );
参数 s 是有函数socket创建,经函数bind绑定到本地某一端口上,然后通过函数listen转化而来的监听套接字。
参数addr用来保存发起连接请求的主机的地址和端口
参数addrlen是addr所指向的结构体大小
流式套接字的数据传输:
发送数据:
函数send用来在TCP套接字上发送数据:
#include
#include
ssize_t send ( int s, const void * msg, size_t len, int flags);
函数send只能对处于连接状态的套接字使用,参数s为已建立好连接的套接字描述符,即accept的返回值。
参数msg指向存放待发送数据的缓冲区
参数len为待发数据的长度
参数flag为控制选项
#define BUFFERSIZI 1500
char send_buf[BUFFERSIZI]
if (send (conn_fd, send_buf , len ,0) < 0)
{
perror("send");
exit(1);
}
接受数据:
函数recv用来在TCP套接字上接受数据:
#include
#include
ssize_t recv(int s, void *buf, size_t len ,int flags);
函数recv从参数s所指定的套接字描述符上接收数据并保存到参数buf所指定的缓冲区,参数len则为缓冲区长度
数据报套接字的数据传输:
发送数据:sendto
接受数据:recvfrom
数据的发送和接受:
sendmsf 函数和recvmsg函数不仅可以用于流式套接口中收发数据,还可以用于数据报套接口中发送和接受数据
关闭套接字:
int close(int s );
int shutdown (int s ,int how);
用来关闭一个套接字描述符,与关闭文件描述符是类似的