网络中的进程是通过套接字socket来通信的

网络中的进程是通过套接字socket来通信的

下面介绍socket相关的函数:

一、服务器端

(1)    socket函数原型:

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

地址族、地址域:domain

常用的协议族有,AF_INET(ipv4)、AF_INET6(ipv6)、

常用的socket类型:type
1.SOCK_STREAM
这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。
2.SOCK_DGRAM
这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。
3.SOCK_RAW
这个socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。

公共协议:protocol

常用的公共协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。默认为0,即选择IPPROTO_TCP。

返回值:

socket返回的值是一个int文件描述,0,1,2分别表示标准输入、标准输出、标准错误。所以其他打开的文件描述符都会大于2, 错误时就返回 -1。

例如:           ret = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP;

                     Printf(“ret=%d\n”, ret);

 

(2)    bind函数原型:

int bind(intsockfd, const struct sockaddr *addr, socklen_t addrlen)

当一个套接字用socket()创建后,存在一个名字空间(地址族),但它没有被命名。bind()将套接字地址(本地主机地址和本地端口地址)与所创建的套接字号联系起来,即将名字赋予套接字,以指定本地半相关。如果没有错误发生,bind()返回0。否则返回SOCKET_ERROR。

sockfd

是socket描述字,它是通过socket()函数创建了,唯一标识一个socket,故这里写socket()函数的返回值。bind()函数就是将给这个描述字绑定一个名字。

addr

一个const struct sockaddr*指针,指向要绑定给sockfd(socket描述字)的协议地址。

ipv4对应的地址是: sockaddr_inipv6对应的地址是: sockaddr_in6

struct sockaddr_in {
    sa_family_t    sin_family; /*  //指代协议簇,TCP套接字编程为AF_INET */
    in_port_t      sin_port;   /* 存储端口(网络字节序),一个16位的无符号整数*/
    struct in_addr sin_addr;   /* 存储IP地址,是一个in_addr结构体internet address */
};
struct in_addr {/* Internet address. */
    uint32_t       s_addr;     /*网络字节序*/
};

addrlen对应的是地址的长度。

例如:    bind (ret, sockaddr_in,20)//通过此函数,就将socket函数所返回的描述字与地址绑定。

网络字节序为大端字节序,由于TCP/IP首部中所有的二进制整数在网络中传输时都要求网络字节序,所以都已大端模式来传输的。所以在使用bind (ret, sockaddr_in,20)将描述字与地址绑定时,务必先将sockaddr_in转为网络字节序后再存放。

下面函数进行转换:

inet_pton ( ) //将ipv4点分十进制数ip地址转换成32位网络字节序

inet_ntop ( ) //将32位网络字节序ip地址转换成点分十进制数ip地址

 ntohs( )//将主机的16位端口转换成网络字节序端口

 htons( ) //将网络字节序的16位端口转换成主机端口

 ntohl( )//将主机的32位端口转换成网络字节序端口

 htonl( ) //将网络字节序的32位端口转换成主机端口

 

(3)    监听函数listen

intlisten(int sockfd, int backlog);

sockfd要监听的客户端的socket描述字

backlog为相应socket可以排队的最大连接个数

TCP服务器端依次调用socket()bind()listen()之后,就会监听指定的socket地址了。

二、客户端

(2)socket函数原型:

用法和服务器的socket函数一样,但这里用于创建客户端套接字。

(1)连接函数connect:

intconnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) ;

sockfd:客户端的socket描述字

addr: 服务器的socket地址

addrlen : socket地址的长度

客户端通过调用connect函数来建立与TCP服务器的连接

客户端依次调用socket()connect()之后就向服务器发送了一个连接请求。服务器监听到这个请求之后,就会调用accept()函数取接收请求,连接建立成功。

三、通信过程

(1) 套接字接受函数accept

intaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

sockfd:为服务器的socket描述字

addr:为指向struct sockaddr *的指针,用于返回客户端的协议地址

addrlen:协议地址的长度

如果accpet成功,返回值是由内核生成的一个新的描述字,代表与客户端的TCP连接。

注意:accept的第一个参数为服务器的socket描述字,该描述字是服务器调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的客户端socket描述字。

一个服务器只创建一个监听socket描述字,在该服务器的生命周期内一直存在。

内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字(客户端socket),当服务器完成了对某个客户的服务,相应的已连接的客户端socket就被关闭。

connect()用于建立连接。accept()用于使服务器等待来自某客户进程的实际连接。

(2)读写函数read()/write()  (recvmsg()/sendmsg())

ssize_t read(int fd, void *buf, size_t count);

read函数是负责从fd中读取内容到buf.当读成功时返回实际所读的字节数,失败时返回-1ssize_t write(int fd, constvoid *buf, size_tcount);

write函数将buf中的count字节内容写入文件描述符fd.成功时返回写的字节数。

失败时返回-1

如果返回错误:EINTR       表示在写的时候出现了中断错误

如果返回错误:EPIPE 表示网络连接出现了问题(对方已经关闭了连接)。

 

(3)关闭相应的socket描述字:close    例如:close(描述字)

在服务器与客户端建立连接之后,会进行一些读写操作,完成了读写操作就要关闭相应的socket描述字,好像要调用fclose关闭打开的文件。 close操作使相应socket描述字的引用计数-1

四、代码实例

Pv4地址结构的bind函数示例:

struct sockaddr_in mysock;

mysock.sin_family =AF_INET;  //TCP地址结构

mysock.sin_port = htons(3333); //端口字节顺序转换

mysock.sin_addr.s_addr = inet_addr(inet_aton("166.111.160.10")); //设置IP地址

服务器和客户端进行通信,那么在服务器和客户端就要分别有一套代码来实现:

服务器端编程的步骤:
1
:创建套接字(socket())
2
:绑定套接字到一个IP地址和一个端口上(bind())
3
:将套接字设置为监听模式等待连接请求(listen())
4
:请求到来后,接受连接请求(accept()),返回一个新的对应于此次连接的套接字;
5
:用返回的套接字和客户端进行通信,即读/(send()/recv())
6
:返回,等待另一连接请求;
7
:关闭套接字,关闭加载的套接字库(close())

 

客户端编程的步骤:
1
:创建套接字(socket())
2
:向服务器发出连接请求(connect())
3
:和服务器端进行通信,即读/(send()/recv())
4
:关闭套接字 (close())

 

实际代码实例参见:

http://blog.csdn.net/fly_yr/article/details/50387065

http://blog.csdn.net/u011819804/article/details/39589489

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值