linux c 笔记 网络编程(二)

套接字

struct sockaddr结构定义了一种通用的套接字地址,他在linux/socket.h中定义如下
struct sockaddr
{
    unsigned short  sa_family;  //套接字的协议簇地址类型,TCP/IP协议对于IPv4地址类型为AF_INET
    char            sa_data[14];//存储具体的协议地址
};

现在一般使用下面这个sockaddr_in结构(用来设置/获取地址信息):
struct sockaddr_in
{
    unsigned short sin_len;      //IPv4地址长度
    short int      sin_family;   //指代协议簇,在TCP套接字编程只能是AF_INET
    unsigned short sin_port;     //存储端口号(使用网络字节顺序),数据类型是一个16为的无符号整形类型
    struct         in_addr sin_addr;//存储IP地址,IP地址是一个in_add结构体(结构在下面)
    unsigned char  sin_zero[8];     //为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节
};
其中,in_addr这个数据结构:
struct sockaddr_in sock;
unsistruct sockaddr_in mysock;
sock.sin_family = AF_INET;                  //TCP地址结构
sock.sin_port = htons(80);                 //设置端口号为80
sock.sin_addr.s_addr = inet_addr("202.205.3.195");    //设置IP地址
memset(sock.sin_zero ,0 , sizeof(sock.sin_zero));    //将数组sin_zero清零

memset函数的原型为
memset(void * s ,int c ,size_t n);

一.创建套接字
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);

domain:用于指定创建套接字所使用的协议族,在头文件<linux/socket.h>中定义。有时候程序中会使用PF_INET,在头文件中AF_INET和PF_INET的数值是一致的。
常见的协议族如下:
    AF_UNIX:创建只在本机内进行通信的套接字。    
    AF_INET:使用IPv4TCP/IP协议
    AF_INET6:使用IPv6 TCP/IP协议
说明:AF_UNIX只能用于单一的UNIX系统进程间通信,而AF_INET是针对Interne的,因而可以允许在远程主机之间通信。一般把它赋为AF_INET。
type:指明套接子通信的类型,对应的参数如下
    SOCK_STREAM:创建TCP流套接字
    SOCK_DGRAM:创建UDP数据报套接字
    SOCK_RAW:创建原始套接字
    protocol:指定某个协议的特定类型
参数protocol通常设置为0,表示通过参数domain指定的协议族和参数type指定的套接字类型来确定使用的协议。当为原始套接字时,系统无法唯一的确定协议,此时就需要使用使用该参数指定所使用的协议。

返回值:执行成功后返回一个新创建的套接字;若有错误发生则返回一个-1,错误代码存入errno中。

下面用代码创建一个TCP套接字
int sock_fd;
sock_fd = socket(AF_INET ,SOCK_STREAM ,0);
if(sock_fd < 0) {
    perror("socket");
    exit(1);
}
创建UDP协议的套接字为
sock_fd = socket(AF_INET ,SOCK_DGRAM ,0);

二.建立连接
    函数connect用来在一个指定的套接字上创建一个连接,该函数原型
    #include <sys/types.h>
    #include <sys/socket.h>
    int connect (int socket ,const struct sockaddr *serv_addr ,socket_t addrlen);

sock_fd:建立套接字时返回的套接字文件描述符,调用socket()返回的。
serv_addr:是一个指向数据结构sockaddr的指针,其中包括客户端需要连接的服务器的目的IP地址和端口号。
addrlen:表示了第二了参数的大小,可以使用sizeof(struct sockaddr)

执行成功后返回0,有错误发生则返回-1,错误代码存入errno中。

通常一个面对连接的套接字(如TCP套接字)只能调用一次connect函数,而面对无连接的套接字(UDP套接字)则可以多次调用connect函数以改变与目的地址的绑定
客户端在建立套接字之后,不需要进行地址绑定,就可以直接连接服务器。连接服务器的函数为connect(),此函数连接指定参数的服务器,例如IP地址,端口号。
如果是TCP编程,则connect()函数用于服务器发出连接请求,服务器的IP地址和端口号由 参数serv_addr指定。
如果是UDP编程,则connect函数并不建立真正的连接,它只是告诉内核与该套接字进行通信的目的地址(由第二个参数指定),只有该目的地址发来的数据才会被该socket接收。调用connect函数的好处是不必在每次发送和接收数据时都指定目的地址。

该函数常见的用法如下
struct sockaddr_in  serv_addr;
memset (&serv_addr , 0 , sizeof(struct sockaddr_in) );     //将serv_addr的各个字段清零
serv_addr.sin_family =AF_INET;
serv_addr.sin_port = htons(80);                //htons是字节顺序转换函数,
// inet_aton函数将一个字符串转换为一个网络地址,并把该网络的地址赋给第二个参数
if(inet_aton("172.17.242.131", &serv_addr.sin_addr) < 0) {
    perror("inet_ation");
    exit(1);
}
//使用sock_fd套接字连接到由serv_addr指定的地址上,假设sock_fd已定义
if(connect(sock_fd, (struct sockaddr *) &serv_addr ,sizeof(struct sockaddr_in )) <0 ) {
    perror("connect");
    exit(1);
}

注意 serv_addr强制类型转换为struct sockaddr类型

三.绑定套接字
函数bind()的作用是将一个套接字文件描述符与地址和端口绑定。
函数bind用来将一个套接字和某个端口绑定在一起,函数的原型
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd ,struct sockaddr *my_addr ,socklen_t addrlen );

sockfd:sockfd是调用socket函数返回的文件描述符;
addrlen是sockaddr结构的长度。
my_addr: 是一个指向sockaddr结构的指针,它保存着本地套接字的地址(即端口和IP地址)信息。
返回:成功返回0,失败返回-1.

该函数的常用方法
struct sockaddr_in  serv_addr;
memset (&serv_addr ,0 , sizeof(struct sockaddr_in ));
serv_addr.sin_family = AF_INEF;
serv_addr.sin_port = htons(80);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

if( bind(sock_fd) ,(struct sockaddr *)&serv_addr ,sizeof(struct sockaddr_in ) < 0) {
    perror("bind");
    exit(1);
}

四.在套接字上监听
函数listen 把套接字转化为被动监听,listen在套接字函数中表示让一个套接字处于监听到来的连接请求的状态,该函数原型
#include <sys/socket.h>
int listen (int s , int backlog);
无错误,返回0,
否则,返回SOCKET ERROR,可以调用函数WSAGetLastError取得错误代码。

listen函数使用主动连接套接字变为被连接套接口,使得一个进程可以接受其它进程的请求,从而成为一个服务器进程。在TCP服务器编程中listen函数把进程变为一个服务器,并指定相应的套接字变为被动连接。
listen函数一般在调用bind之后-调用accept之前调用。
该函数常见用法
#define LISTEN_NUM  12     //定义连接请求队列长度
....
if(listen (sock_fd , LISTEN_NUM) < 0) {
    perror ("listen ");
    exit(1);
}

五.接受连接
函数accept用来接受一个连接请求,该函数原型
#include <sys/types.h>
#include <sys/socket.h>
int accept(int s ,struct sockaddr *addr ,socklen_t *addrlen);
参数
s:由函数socket创建,经函数bind绑定到本地某一端口上,然后通过函数listen转化而来的监听套接字.
addr:用来保存发起连接请求的主机的地址和端口
addrlen:是addr所指向的结构体的大小

执行成功返回一个新的代表客户端的套接字,出错则返回-1,错误代码存入errno中,详细带错误代码手册参考man手册

返回值:accept()函数的返回值是新连接的客户端套接字文件描述符,与客户端之间的通信是通过accept()返回的新套接字文件描述符来进行的,而不是通过建立套接字时的文件描述符。如果accept()函数发生错误,accept()会返回-1,通过errno可以得到错误值。

如果参数sock_fd所指定的套接字被设置为阻塞方式(Linux下的默认方式),且连接请求队列为空,则accept()将被阻塞直到有连接请求到此为止;如果参数s所指定的套接字被设置为非阻塞方式,如果队列为空,accept将立即返回-1,errno被设置为EAGAIN.

套接字为阻塞方式下该函数的常见方法
int client_fd;
int client_len;
struct sockaddr_in  client_addr;
...
client_len = sizeof(struct sockaddr_in);
client_fd = accept(sock_fd , (struct sockaddr *)&client_addr , &client_len );
if (conn_fd < 0) {
    perror("accpt");
    exit(1);
}

时间: 2024-10-05 14:25:48

linux c 笔记 网络编程(二)的相关文章

安卓第八天笔记--网络编程二

安卓第八天笔记--网络编程二 1.网络图片查看器 /** * 网络图片查看器 * 1.获取输入的URL地址,判断是否为空 * 2.建立子线程,获取URl对象new URL(path) * 3.打开连接获取HttpURLConnection conn = (HttpURLConnection) url.openConnection(); * 4.设置连接超时时间conn.setConnectionTimeOut(5000)毫秒 * 5.设置请求方式setRequestMethod * GET或者P

linux c 笔记 网络编程(一)

1) 链路层,有时也称作数据链路层或网络接口层,通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡.它们一起处理与电缆(或其他任何传输媒介)的物理接口细节.2) 网络层,有时也称作互联网层,处理分组在网络中的活动,例如分组的选路.在TCP/IP协议族中,网络层协议包括IP协议(网际协议),ICMP协议(internet互联网控制报文协议),以及IGMP协议(internet组治理协议).3 )传输层主要为两台主机上的应用程序提供端到端的通信.在TCP/IP协议族中,有两个互不相同的传输协

Linux程序设计学习笔记----网络编程之网络数据包拆封包与字节顺序大小端

网络数据包的封包与拆包 过程如下: 将数据从一台计算机通过一定的路径发送到另一台计算机.应用层数据通过协议栈发到网络上时,每层协议都要加上一个数据首部(header),称为封装(Encapsulation),如下图所示: 不同的协议层对数据包有不同的称谓,在传输层叫做段(segment),在网络层叫做数据包(packet),在链路层叫做帧(frame).数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,最后将应用层数据交给应用程序处理. 上图对应两台计算机在同一网段中的情况,

Linux网络编程(二)

服务套和客户机的信息函数 1.字节转换函数 在网络上面有着许多类型的机器,这些机器在表示数据的字节顺序是不同的, 比如i386芯片是低字节在内存地址的低端,高字节在高端,而alpha芯片却相反. 为了统一起来,在Linux下面,有专门的字节转换函数. unsigned long int htonl(unsigned long int hostlong)     unsigned short int htons(unisgned short int hostshort)     unsigned

Linux下TCP网络编程与基于Windows下C#socket编程间通信

一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使socket处于被动的监听模式,并为该  socket  建立一个输入数据队列,将到达的服务器, 请求保存在此队列中,直到程序处理他们. Accept():让服务器接收客户的连接请求. Connect():客户端使用connect函数来配置 socket并与远端服务器建立一个 TCP 连接. Clos

Linux下TCP网络编程与基于Windows下C#socket编程之间通信

一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使socket处于被动的监听模式,并为该  socket  建立一个输入 数据队列,将到达的服务器, 请求保存在此队列中,直到程序处理他们. Accept():让服务器接收客户的连接请求. Connect():客户端使用connect函数来配置 socket并与远端服务器建立一个 TCP 连接. Clo

IOS学习笔记 -- 网络编程

一.HTTP协议1.面试题: 聊一下HTTP协议(表达对HTTP协议的看法)* HTTP协议的全称: 超文本传输协议, 定制传输数据的规范(客户端和服务器之间的数据传输规范)* 描述HTTP协议完整的通信过程 2.通信过程1> 请求* 客户端 --> 服务器* 请求的内容a."请求行" : 请求方法\请求资源路径\HTTP协议版本GET /MJServer/login?username=123&pwd=123&method=get&type=JSON

7)Linux程序设计入门--网络编程

8)Linux程序设计入门--网络编程 Linux系统的一个主要特点是他的网络功能非常强大.随着网络的日益普及,基于网络的 应用也将越来越多. 在这个网络时代,掌握了Linux的网络编程技术,将令每一个人处 于不败之地,学习Linux的网络编程,可以让我们真正的体会到网络的魅力. 想成为一 位真正的hacker,必须掌握网络编程技术. 现在书店里面已经有了许多关于Linux网络编程方面的书籍,网络上也有了许多关于 网络编程方面的教材,大家都可以 去看一看的.在这里我会和大家一起来领会Linux网

winform网络编程(二)

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了.这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies .disc_copies都可能会发生. 如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2 mnesia过载分析 1.抛出警告是在mnesia 增加dump