使用linux套接字访问网页,Linux下的套接字使用

1.2.2

bind函数绑定端口实例

下面的实例使用了bind函数在一个打开的socket上面绑定IP与端口。绑定的端口是5678,IP为INADDR_ANY,表示本地计算机的默认IP地址。

代码17-1 bind函数绑定端口:\源文件\17\17.19.c

#include

#include

#include

#include

#include

#define PORT 5678

main()

{

int sockfd,newsockfd, fd; struct sockaddr_in addr;

int addr_len = sizeof(struct sockaddr_in);

fd_set myreadfds;

char msgbuffer[256];

if ((sockfd = socket(AF_INET,SOCK_STREAM,0))<0) {

perror("socket");

exit(1);

}

else {

printf("socket created .\n");

printf("socked id: %d \n",sockfd);

}

bzero(&addr,sizeof(addr)); addr.sin_family =AF_INET;

addr.sin_port = htons(PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY);

if(bind(sockfd,&addr,sizeof(addr))<0) {

perror("connect");

exit(1);

}

else {

printf("connected.\n");

printf("local port:%d\n",PORT) ;

}

}

输入下面的命令,编译这个程序。

gcc 17.19.c

输入下面的命令,对这个程序添加可执行权限。

chmod +x a.out

输入下面的命令,运行这个程序。

./a.out

程序的运行结果如下所示。

socket created .

socked id: 3

connected.

local port:5678

1.3 监听与连接

所谓监听,指的是socket的端口处于等待状态,如果客户端有连接请求,这个端口会接受这个连接。连接指的是客户端向服务端发送一个通信申请,服务端会响应这个请求。本节将讲述socket的监听与连接操作。

1.3.1 等待监听函数listen

服务器必须等待客户端的连接请求,listen函数用于实现监听等待功能。这个函数的使用方法如下所示。

int listen(int s,int backlog);

在参数列表中,s表示已经建立的socket,backlog表示能同时处理的最大连接请求,如果超过这个数目,客户端将会接收到ECONNREFUSED拒绝连接的错误。需要注意的是,listen并未真正的接受连接,只是设置socket的状态为listen模式,真正接受客户端连接的是accept函数。通常情况下,listen函数会在socket,

bind函数之后调用,然后才会调用accept函数。

listen函数只适用SOCK_STREAM或SOCK_SEQPACKET的socket类型。如果socket为AF_INET则参数backlog最大值可设至128,即最多可以同时接受128个客户端的请求。

如果调用成功,则函数的返回值为0,失败返回-1。函数可能发生如下所示的错误,可以用errno来捕获发生的错误。

 EBADF:参数sockfd不是一个合法的socket。

 EACCESS:权限不足。

 EOPNOTSUPP:指定的socket不支持listen模式。

在使用这个函数前,需要在程序的最前面包含下面的头文件。

#include

1.3.2 listen函数使用实例

本节将讲述一个listen函数使用实例。在程序中,先建立一个socket,然后用bind函数在这个socket上面绑定端口与IP,然后用listen函数设置这个socket进行监听。程序的代码如下所示。

代码17-2 listen函数监听端口:\源文件\17\17.20.c

#include

#include

#include

#include

#include

#define PORT 5678 #define MAX 10

main()

{

int sockfd,newsockfd,is_connected[MAX],fd; struct sockaddr_in addr;

int addr_len = sizeof(struct sockaddr_in);

fd_set myreadfds;

char msgbuffer[256];

char msg[] ="This is the message from server.Connected.\n";

if ((sockfd = socket(AF_INET,SOCK_STREAM,0))<0) {

perror("socket");

exit(1);

}

else {

printf("socket created .\n");

printf("socked id: %d \n",sockfd);

}

bzero(&addr,sizeof(addr)); addr.sin_family =AF_INET; addr.sin_port = htons(PORT);

addr.sin_addr.s_addr = htonl(INADDR_ANY);

if(bind(sockfd,&addr,sizeof(addr))<0) {

perror("connect");

exit(1);

}

else {

printf("connected.\n");

printf("local port:%d\n",PORT) ;

}

if(listen(sockfd,3)<0) {

perror("listen"); exit(1);

}

else {

printf("listenning......\n"); }

}

输入下面的命令,编译这个程序。

gcc 17.20.c

输入下面的命令,对这个程序添加可执行权限。

chmod +x a.out

输入下面的命令,运行这个程序。

./a.out

程序的运行结果如下所示。

socket created .

socked id: 3

connected.

local port:5678

listenning......

1.3.3 接受连接函数accept

服务器处于监听状态时,如果获得客户机的请求会将这个请求放在等待队列中,当系统空闲时将处理客户机的连接请求。接受连接请求的函数是accept,这个函数的使用方法如下所示。

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

在参数列表中,s表示处于监听状态的socket,addr是一个sockaddr结构体类型的指针,系统会把远程主机的这些信息保存到这个结构体指针上,addrlen表示sockaddr的内存长度,可以用sizeof函数来取得。

当accept函数接受一个连接时,会返回一个新的socket编号。以后的数据传输与读取就是通过这个新的socket编号来处理。原来参数中的socket可以继续使用。接受连接以后,远程主机的地址和端口信息将会保存到addr所指的结构体内。如果处理失败,返回值为-1。函数可能产生下面的错误,可以用error来捕获发生的错误。

EBADF:参数s不是一个合法的socket代码。

 EFAULT:参数addr指针指向无法存取的内存空间。

 ENOTSOCK 参数s为一文件描述词,而不是一个socket。

 EOPNOTSUPP:指定的socket不是SOCK_STREAM。

 EPERM:防火墙拒绝这一个连接。

 ENOBUFS:系统的缓冲内存不足。

 ENOMEM:核心内存不足。

在使用这个函数前,需要在程序中包含下面的头文件。

#include

#include

1.3.4

accept函数使用实例

本节将讲述一个accept函数使用实例。在程序中,先建立一个socket,然后用bind函数在这个socket函数上面绑定一个端口,然后使用listen函数使这个端口处于监听状态。当有连接请求时,accpet函数会产生一个新的socket,然后输出提示信息。程序的代码如下所示。

代码17-3

accept函数接受连接:\源文件\17\17.21.c

#include

#include

#include

#include

#include

#define PORT 5678

main()

{

int sockfd,newsockfd,fd;

struct sockaddr_in addr;

int addr_len = sizeof(struct sockaddr_in);

fd_set myreadfds;

char msgbuffer[256];

if ((sockfd = socket(AF_INET,SOCK_STREAM,0))<0)

{

perror("socket");

exit(1);

}

else

{

printf("socket created .\n");

printf("socked id: %d \n",sockfd);

}

bzero(&addr,sizeof(addr));

addr.sin_family =AF_INET;

addr.sin_port = htons(PORT);

addr.sin_addr.s_addr = htonl(INADDR_ANY);

if(bind(sockfd,&addr,sizeof(addr))<0)

{

perror("connect");

exit(1);

}

else

{

printf("connected.\n");

printf("local port:%d\n",PORT) ;

}

if(listen(sockfd,3)<0)

{

perror("listen");

exit(1);

}

else

{

printf("listenning......\n");

}

if((newsockfd = accept (sockfd,&addr,&addr_len))<0)

{

perror("accept");

}

else

{

printf("accepted a new connecttion.\n");

}

}

输入下面的命令,编译这个程序。

gcc 17.21.c

输入下面的命令,对这个程序添加可执行权限。

chmod +x a.out

输入下面的命令,运行这个程序。

./a.out

程序的运行结果如下所示。

socket created .

socked id: 3

connected.

local port:5678

listenning......

结果表明,本地计算机的5678号端口处于监听状态。打开浏览器,在浏览器的地址栏中输入下面的网址,然后按“Enter”键。这样浏览器会请求连接本地计算机的5678号端口。

浏览器会显示无法打开这个网页。在终端中显示的结果如下所示。表明这个程序已经接受了这个连接,然后退出了程序。

accepted a new connecttion.

1.3.5 请求连接函数connet

所谓请求连接,指的是客户机向服务器发送信息时,需要发送一个连接请求。connect函数可以完成这项功能,这个函数的使用方法如下所示。

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

在参数列表中,sockfd表示已经建立的socket,serv_addr是一个结构体指针,指向一个sockaddr结构体,这个结构体存储着远程服务器的IP与端口信息,Addrlen表示sockaddr结构体的内存长度,可以用sizeof函数来获取。sockaddr结构体的定义见前面节中的bind函数所述。

函数会将本地的socket连接到serv_addr所指定的服务器IP与端口。如果连接成功,返回值为0,连接失败则返回-1。函数可能发生下面的错误,可以用error来捕获发生的错误。

 EBADF:参数sockfd 不是一个合法的socket。

 EFAULT:参数serv_addr指针指向了一个无法读取的内存空间。

 ENOTSOCK:参数sockfd是文件描述词,而不是一个正常的socket。

 EISCONN:参数sockfd的socket已经处于连接状态。

 ECONNREFUSED:连接要求被服务器拒绝。

 ETIMEDOUT:需要的连接操作超过限定时间仍未得到响应。

 ENETUNREACH:无法传送数据包至指定的主机。

 EAFNOSUPPORT:sockaddr结构的sa_family不正确。

 EALREADY:socket不能阻断,但是以前的连接操作还未完成。

如果需要使用这个函数,需要在程序的最前面包含下面的头文件。

#include

#include

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值