Linux网络编程

1 套接字地址结构

struct sockaddr{
  unsigned short sa_family;//地址类型
  char sa_data[14]; //14字节的地址协议
}

sa_family表示套接字的协议族类型,对应于TCP/IP的协议该是AF_INET;

与该结构体等价的另一个数据结构:sockaddr_in。

struct sockaddr_in

{

  unsigned short sin_family; //地址类型

  unsigned short sin_port ; //端口号

  struct  in_addr sin_addr ;//IP地址

  unsigned char   sin_zero[8];//填充字节,一般为0 

}

struct in_addr {

  unsigned long s_addr;

};

结构体sockaddr和结构体sockaddr_in都是16个字节。通常在编写基于TCP/IP协议的网络程序的时候,使用sockaddr_in来设置地址,然后通过类型的强制转换成sockaddr类型。

struct sockaddr_in sock;

sock.sin_family = AF_INET;

sock.sin_port = htons(80);

sock.sin_addr.s_addr = inet_addr("202.112.12.11");

memset(sock.sin_zero, 0, sizeof(sock.sin_zero)); //将数组sin_zero设置成为0

 

2 创建套接字

#include <sys/types.h>

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

domain用来表示套接字所使用的协议族。AF_UNIX:在本机通讯的套接字;AF_INET:使用ipv4; AF_INET6:使用ipv6。

type指示套接字的类型。SOCK_STREAM    SOCK_DGRAM    SOCK_RAW

 

3 建立连接

函数connect用来在一个执行的套接字上穿件一个连接。

#include <sys/types.h>

#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);

服务器的IP地址和端口号由serv_addr来制定。

 

4 绑定套接字

int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);

这个函数只有服务器端使用。

5 在套接字上侦听

int listen(int s, int backlog);

在服务器端,一般先创建一个socket,然后调用函数bind将该套接字绑定到某个端口上,接着调用listen函数等待来自于客户端的连接请求。

一般多个客户端连接到一个服务器,服务器设置一个连接队列,记录已经建立的连接,参数backlog指定了该连接队列的最大长度。如果连接队列已经达到最大,

之后的连接请求将会被服务器拒绝。

6 接受连接

int accept(int s, struct sockaddr *addr, socklen_t *addrlen);

参数s是由函数socket创建,经函数bind绑定到本地某一端口上,然后通过函数listen转化而来的监听套接字。

参数addr是用来保存发起连接请求的主机的地址和端口。

参数addrlen是addr所指向的结构体的大小。

只能对面向连接的套接字使用accept函数。accept成功时,将创建一个新的套接字,并为这个新的套接字分配一个新的套接字描述符,类似文件描述符,进程可以利用这个新的套接字描述符与客户端交换数据。参数S指定的套接字将继续等待客户端的连接请求。

如果参数s指向的套接字被设置成为阻塞方式(Linux默认的设置),且连接请求队列为空的时候,则accept函数将被阻塞直到有连接请求为止;

如果参数s指向的套接字被设置成为非阻塞方式(fcntl),如果队列为空,则accept立即返回-1,errno设置成为EAGAIN。

7 TCP套接字 发送数据

size_t send(int s, const void *msg, size_t len, int flags);

函数send只能对处于连接状态的套杰斯使用。参数S为已建立好连接的套接字描述符,即accept函数的返回值。

参数msg指向存放待发数据的缓冲区,参数len为待发数据的长度。

如果要发送的数据太长而不能发送时,将出现错误,error设置成为EMSGSIZE;

如果要发送的数据长度大于该套接字的缓冲区剩余空间大小时,send()一般会被阻塞,如果该套接字设置成为非阻塞方式,则此时立即返回-1.

执行成功则返回实际发送的数据的字节数。

执行成功只能说明数据写入套接字的缓冲区中,并不表示数据已经成功的通过网络发送到目的地。

8 接受数据

size_t recv(int s, coid *buf, size_t len, int flags);

如果一个数据包太长以至于缓冲区放不下的时候,剩余部分的数据将可能被丢弃。

如果在指定的套接字上无数据到达时,recv函数将被阻塞,如果套接字设置成为非阻塞的话,则立即返回-1;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(linux)