TCP套接字的数据传输
1.传送数据
函数seed用来在TCP套接字上发送数据,函数原型
#include <sys/socket.h>
#include <sys/types.h>
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);
}
2.接受数据:
函数recv用来在TCP套接字上接受数据:
#include <sys/socket.h>
#include <sys/types.h>
ssize_t recv(int s, void *buf, size_t len ,int flags);
函数recv从参数s所指定的套接字描述符上接收数据并保存到参数buf所指定的缓冲区,参数len则为缓冲区长度
常见用法
char recv_buf[BUFFERSIZE];
...
if ( recv(conn_fd ,recv_buf , sizeof (recv_buf ) ,0 ) < 0 ) {
perror("recv");
exit(1);
}
UDP套接字的数据传输
1.发送数据:
函数sendto用来在UDP套接字上发送数据
#include <sys/socket.h>
#include <sys/types.h>
ssize_t sendto(int s,const void *msg,size_t len,int flags,const struct sockaddr *to,socklen_t tolen);
const struct sockaddr *to ;
函数功能与函数send类似,但函数sendto不需要套接字处于连接状态,所以该函数通常用来发送UDP数据,同时因为是无连接的套接字,在使用sendto时需要指定数据的目的地址,参数msg指向待发送数据的缓冲区。
参数len指定了待发送数据的长度
参数flags是控制选项,含义与send函数中的一致
参数to用于指定目的地址,目的地址的长度由tolen指定
该函数常见的用法
char seed_buf[BUFFERSIZE];
struct sockaddr_in dest_addr;
//设置目的地址
memset(&dest_addr ,0 , sizeof(struct sockaddr_in ));
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(DEST_PORT);
if(inet_aton("172.17.242.131",&dest_addr.sin_addr ) < 0) {
perror("inet_aton");
exit(1);
}
if(sendto(sock_fd ,send_buf , len ,0 ,(struct sockaddr *)&dest_addr ,sizeof(struct sockaddr_in) ) < 0) {
perror("sento ");
exit(1);
}
2.接受数据:recvfrom
数据的发送和接受:
函数recvfrom用来在UDP套接字上接受数据,函数原型:
#include <sys/socket.h>
#include <sys/types.h>
ssize_t recvfrom(int s ,void *buf,size_t len,int flags,struct sockaddr *from,socklen_t *fromlen);
与函数recv功能类似,只是函数recv只能用于面向连接的套接字,而函数recvfrom没有此限制,可以用于从无连接的套接字上接收数据
参数buf指向接收缓冲区
参数len指定了缓冲区的大小
参数flags是控制选项,含义与recv中的一致
如果参数from非空,且该套接字不是面向连接的,则函数recvfrom返回时,参数from中将保存数据的源地址
参数fromlen在调用recvfrom前为参数from的长度,调用recvfrom后将保存from的实际大小
套接字为阻塞方式下该函数的常见用法
char recv_buf[BUFFERSIZE];
struct sockaddr_in src_addr;
int src_len;
src_len = sizeof(struct sockaddr_in);
if(recvfrom (sock_fd ,recv_buf , sizeof(recv_buf ) ,0 ,(struct sockaddr *)&src_addr ,&src_len ) < 0) {
perror("again_recvfrom");
exit(1);
}
关闭套接字:
#include <unistd.h>
int close(int fd );
fd 为一个套接字的描述符,请函数关闭一个套接字
执行成功返回0,出错返回-1,错误代码存入errno中
#include <sys/socket.h>
int shutdown (int s ,int how);
用来关闭一个套接字描述符,与关闭文件描述符是类似的
它允许对套接字进行单向关闭或者全部关闭,参数s为待关闭的套接字
参数 how 指定了关闭方式,具体取值如下:
SHUT_RD : 将连接上的读通道关闭,此后进程将不能再接收到任何数据,接收缓冲区中还未被读取的数据也将被丢弃,但仍然可以在该套接字上发送数据。
SHUT_WR : 将连接上的写通道关闭,此后进程将不能再发送任何数据,发送缓冲区中还未被发送的数据也将被丢弃,但仍然可以在该套接字上接收数据。
SHUT_RDWR : 读、写通道都将被关闭。
执行成功返回 0,出错则返回 -1,错误代码存入 errno 中。
下面摘用网上的一段话来说明二者的区别:
close-----关闭本进程的socket id,但链接还是开着的,用这个socket id的其它进程还能用这个链接,能读或写这个socket id
shutdown--则破坏了socket 链接,读的时候可能侦探到EOF结束符,写的时候可能会收到一个SIGPIPE信号,这个信号可能直到