基于Linux的TCP网络编程文档格式.docx
- 文档编号:19513876
- 上传时间:2023-01-07
- 格式:DOCX
- 页数:14
- 大小:22.79KB
基于Linux的TCP网络编程文档格式.docx
《基于Linux的TCP网络编程文档格式.docx》由会员分享,可在线阅读,更多相关《基于Linux的TCP网络编程文档格式.docx(14页珍藏版)》请在冰豆网上搜索。
1.socket
函数原型:
intsocket(intdomain,inttype,intprotocol)
函数功能:
函数socket()用于创建一个套接字描述符。
形参:
domain:
用于指定创建套接字所使用的协议族,在头文件
<
linux/socket.h>
中定义。
有时候程序中会使用PF_INET,在头文件中AF_INET和PF_INET的数值是一致的。
常见的协议族如下:
AF_UNIX:
创建只在本机内进行通信的套接字。
AF_INET:
使用IPv4TCP/IP协议
AF_INET6:
使用IPv6TCP/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中。
举例:
调用socket函数创建一个UDP套接字
intsock_fd;
sock_fd=socket(AF_INET,SOCK_DGRAM,0);
if(sock_fd<
0){
perror(“socket”);
exit
(1);
}
2.bind
函数原型:
intbind(intsockfd,structsockaddr*my_addr,socklen_taddrlen)
函数功能
函数bind()的作用是将一个套接字文件描述符与地址和端口绑定。
sockfd:
sockfd是调用socket函数返回的文件描述符;
addrlen是sockaddr结构的长度。
my_addr:
是一个指向sockaddr结构的指针,它保存着本地套接字的地址(即端口和IP地址)信息。
不过由于系统兼容性的问题,一般不使用这个结构,而使用另外一个结构(structsockaddr_in)来代替
套接字地址结构:
(1)structsockaddr:
结构struct
sockaddr定义了一种通用的套接字地址,它在
sys/socket.h中定义。
structsockaddr{
unsignedshort
sa_family;
/*地址类型,AF_XXX*/
char
sa_data[14];
/*14字节的协议地址*/
a.sin_family:
表示地址类型,对于使用TCP/IP协议进行的网络编程,该值只能是AF_INET.
b.sa_data:
存储具体的协议地址。
(2)sockaddr_in
每种协议族都有自己的协议地址格式,TCP/IP协议组的地址格式为结构体structsockaddr_in,它在netinet/in.h头文件中定义。
structsockaddr_in{
unsignedshort
sin_family;
/*地址类型*/
sin_port;
/*端口号*/
structin_addr
sin_addr;
/*IP地址*/
unsignedchar
sin_zero[8];
/*填充字节,一般赋值为0*/
b.sin_port:
是端口号
c.sin_addr:
用来存储32位的IP地址。
d.数组sin_zero为填充字段,一般赋值为0.
e.structin_addr的定义如下:
structin_addr{
unsignedlongs_addr;
结构体sockaddr的长度为16字节,结构体sockaddr_in的长度为16字节。
可以将参数my_addr的sin_addr设置为INADDR_ANY而不是某个确定的IP地址就可以绑定到任何网络接口。
对于只有一IP地址的计算机,INADDR_ANY对应的就是它的IP地址;
对于多宿主主机(拥有多个网卡),INADDR_ANY表示本服务器程序将处理来自所有网络接口上相应端口的连接请求
函数成功后返回0,当有错误发生时则返回-1,错误代码存入errno中。
举例:
structsockaddr_inaddr_serv,addr_client;
/*本地的地址信息*/
memset(&
serv_addr,0,sizeof(structsockaddr_in));
addr_serv.sin_family=AF_INET;
/*协议族*/
addr_serv.sin_port=htons(SERV_PORT);
/*本地端口号*/
addr_serv.sin_addr.s_addr=htonl(INADDR_ANY);
/*任意本地地址*/
/*套接字绑定*/
if(bind(sock_fd,(structsockaddr*)&
addr_serv),sizeof(structsockaddr_in))<
0)
{
perror(“bind”);
3.监听本地端口listen()
函数功能:
函数listen()用来初始化服务器可连接队列,服务器处理客户端连接请求的时候是顺序处理的,同一时间仅能处理一个客户端连接。
当多个客户端的连接请求同时到来的时候,服务器并不是同时处理,而是将不能处理的客户端连接请求放到等待队列中,这个队列的长度由listen()函数来定义。
函数原型:
#includ<
sys/socket.h>
intlisten(intsockfd,intbacklog);
形参
sockfd是调用socket函数返回的文件描述符
backlog:
指定该连接队列的最大长度。
如果连接队列已经达到最大,之后的连接请求被服务器拒绝。
大多数系统的设置为20,可以将其设置修改为5或者10,根据系统可承受负载或者应用程序的需求来确定。
返回值:
当listen()函数成功运行时,返回值为0;
当运行失败时,它的返回值为-1,错误代码存入errno中。
.listen()函数的例子:
#defineSERV_PORT3000
intmain(intargc,char*argv[])
//设置服务器侦听队列的长度
if(listen(sock_fd,5)<
0){
perror(“listen”);
4.accept(接收一个网络请求)
当一个客户端的连接请求到达服务器主机侦听的端口时,此时客户端的连接会在队列中等待,知道使用服务器处理接收请求。
函数accept()成功执行后,会返回一个新的套接口文件描述符来表示客户端的连接,客户端连接的信息可以通过这个新描述符来获得。
因此当服务器成功处理客户端的请求连接后,会有两个文件描述符,老的文件描述符表示客户端的连接,函数send()和recv()通过新的文件描述符进行数据收发。
#include<
sys/types.h>
int
accept(intsock_fd,structsockaddr*addr,socklen_t*addrlen);
sock_fd:
是由函数socket创建,经函数bind绑定到本地某一端口上,然后通过函数listen转化而来的监听套接字。
addr:
用来保存发起连接请求的主机的地址和端口。
addrlen是addr所指向的结构体的大小。
accept()函数的返回值是新连接的客户端套接字文件描述符,与客户端之间的通信是通过accept()返回的新套接字文件描述符来进行的,而不是通过建立套接字时的文件描述符。
如果accept()函数发生错误,accept()会返回-1,通过errno可以得到错误值。
如果参数sock_fd所指定的套接字被设置为阻塞方式(Linux下的默认方式),且连接请求队列为空,则accept()将被阻塞直到有连接请求到此为止;
如果参数s所指定的套接字被设置为非阻塞方式,如果队列为空,accept将立即返回-1,errno被设置为EAGAIN.
实例:
intclient_fd;
intclient_len;
structsockaddr_in
client_addr;
client_len=sizeof(structsockaddr_in);
client_fd=accept(sock_fd,(structsockaddr*)&
client_addr,&
client_len);
if(conn_fd<
perror(“accept”);
exit
(1);
5.connect(连接目标网络服务器)
客户端在建立套接字之后,不需要进行地址绑定,就可以直接连接服务器。
连接服务器的函数为connect(),此函数连接指定参数的服务器,例如IP地址,端口号。
如果是TCP编程,则connect()函数用于服务器发出连接请求,服务器的IP地址和端口号由参数serv_addr指定。
如果是UDP编程,则connect函数并不建立真正的连接,它只是告诉内核与该套接字进行通信的目的地址(由第二个参数指定),只有该目的地址发来的数据才会被该socket接收。
调用connect函数的好处是不必在每次发送和接收数据时都指定目的地址。
intconnect(intsock_fd,structsockaddr
*serv_addr,socklen_taddrlen);
形参:
建立套接字时返回的套接字文件描述符,调用socket()返回的。
serv_addr:
是一个指向数据结构sockaddr的指针,其中包括客户端需要连接的服务器的目的IP地址和端口号。
addrlen:
表示了第二了参数的大小,可以使用sizeof(structsockaddr)
执行成功后返回0,有错误发生则返回-1,错误代码存入errno中。
structsockaddr_inserv_addr;
if(-1==(sock_fd==socket(AF_INET,SOCK_STREAM,0))){
printf(“Error:
Unabletocreatesocket(%i)…\n”,errno);
perror(“sockets”);
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(DEST_PORT);
serv_addr.sin_addr.s_addr=inet(DEST_IP_ADDRESS);
if(-1==connect(sock_fd,(structsockaddr*)&
serv_add,sizeof(structsockaddr))){
unabletotheestablishconnectiontosocket(%i)…\n”,errno);
perror(“socks”);
close(sock_fd);
6.send(发送数据)
函数send用来在TCP套接字上发送数据,send只能对处于连接状态的套接字使用。
函数原型
ssize_tsend(intconn_fd,constvoid*msg,size_tlen,intflags);
函数形参:
conn_fd:
为已建立好连接的套接字描述符,即调用accept()函数后返回的套接字描述符。
msg:
存放发送数据的缓冲区。
len:
发送缓冲区的长度
flags:
为控制选项,一般设置为0,或取以下值:
²
MSG_OOB:
在指定的套接字上发送带外数据(out-of-banddata),该类型的套接字必须支持带外数据(如:
SOCK_STREAM).
MSG_DONTROUTE:
通过最直接的路径发送数据,而忽略下层协议的路由设置。
执行成功返回实际发送数据的字节数,出错则返回-1,错误代码存入errno中。
执行成功只是说明数据写入套接字的缓冲区中,并不表示数据已经成功地通过网络发送到目的地。
#define
BUFFERSIZE
1500
char
send_buf[BUFFERSIZE];
……
if(send(conn_fd,send_buf,len,0)<
perror(“send”);
}
7.recv(接收数据)
recv()用来TCP套接字上接收数据。
函数recv从指定的套接字描述符上接收数据并保存到指定buf中。
ssize_trecv(intconn_fd,void*buf,size_tlen,intflags);
为已建立好连接的套接字描述符,即调用accept()函数后返回的套接字描述符
buf:
接收缓冲区
接收缓冲区的大小
为控制选项,一般设置为0或取以下数值
请求接收带外数据
MSG_PEEK:
只查看数据而不读出
MSG_WAITALL:
只在接收缓冲区满时才返回。
函数返回值
函数执行成功返回接收到的数据字节数,出错返回-1,错误代码存入errno中。
recv_buf[BUFFERSIZE];
if(recv(conn_fd,recv_buf,sizeof(recv_buf),0)<
perror(“recv”);
8.close
close(intfd);
函数close用来关闭一个套接字描述符。
参数fd为一个套接字描述符。
执行成功返回0,出错则返回-1.错误代码存入errno中。
close()函数的头文件是#include<
unistd.h>
.
三.基于Linux的TCP套接字编程实例
1.实例程序分为服务器端和客户端,客户端把Hellotigerjibo发送给服务器端;
服务器端接收到字符串后,发送接收到的总字符串个数给客户端;
2.服务器端程序:
1#include<
stdio.h>
2#include<
stdlib.h>
3#include<
string.h>
4#include<
errno.h>
5
6
7#include<
8#include<
9#include<
//close()
10#include<
netinet/in.h>
//structsockaddr_in
11#include<
arpa/inet.h>
//inet_ntoa
12#define
QUEUE_LINE
12
13#define
SOURCE_PORT8000
14
15#define
SOURCE_IP_ADDRESS"
192.168.1.6"
16
17voidprocess_info(ints)
18{
19
intrecv_num;
20
intsend_num;
21
charrecv_buf[50];
22
charsend_buf[50];
23
while
(1){
24
printf("
beginrecv:
\n"
);
25
recv_num=recv(s,recv_buf,sizeof(recv_buf),0);
26
if(recv_num<
27
perror("
recv"
28
29
}else{
30
recv_buf[recv_num]='
\0'
;
31
recvsucessful:
%s\n"
recv_buf);
32
}
33
sprintf(send_buf,"
recv%dnumbersbytes\n"
recv_num);
34
beginsend\n"
35
send_num=send(s,send_buf,sizeof(send_buf),0);
36
if(send_num<
37
sned"
38
39
40
sendsucess\n"
41
42
43}
44intmain()
45{
46
intsock_fd,conn_fd;
47
intclient_len;
48
pid_tpid;
49
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 Linux TCP 网络 编程