您的位置:首页 > 编程语言

socket编程(二)---- 简单的服务器端

2016-03-21 20:43 288 查看
socket编程(二)---- 简单的服务器端

1. socket通信流程



2. socket服务器端函数描述

socket()

#include <sys/types.h>
#include <sys/socket.h>

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


创建一个socket套接字,

domail:协议域,又称协议族,一般为 AF_INET (IPv4 Internet protocols)

type:指定套接字类型, 一般为SOCK_STREAM(流式套接字)

protocol:指定协议,一般传参0

如果创建套接字成功,返回一个套接字的文件描述符,如果失败,返回-1

详见手册 man socket

bind()

#include <sys/types.h>
#include <sys/socket.h>

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


将本地地址与一套接字绑定

sockfd:创建的套接字的文件描述符

addr:套接字地址结构

addrlen:套接字地址大小

如果绑定地址成功返回0,失败返回-1

详见手册 man bind

listen()

#include <sys/types.h>
#include <sys/socket.h>

int listen(int sockfd, int backlog);


监听,将创建的套接字转变为被动套接字

sockfd:已绑定的套接字的文件描述符

backlog:等待连接队列的最大长度

如果监听成功则返回0,否则返回-1

详见手册 man accept

accept()

#include <sys/socket.h>

int accept(int socket, struct sockaddr *restrict address,
socklen_t *restrict address_len);


从连接队列中获取一个连接,注意,当客户端向服务器发送一个连接请求时,该客户端会直接和服务器在后台进行三次握手,此时对accept函数是不可见的,当握手完成,该链接会被保存到一个队列之中,而accept函数则是从该队列中获取一个连接,顾在accept之前,就已经建立了连接。

sockfd:已绑定的套接字的文件描述符

address:如果accept到了连接,那么将客户端的地址等信息写到该结构体中。

address_len:address结构体的空间大小

如果accept到了一个链接,那么返回一个关于这个链接的文件描述符,accept失败则返回-1,如果没有链接到来,该函数会阻塞

详见手册 man 3 accept

3. 搭建一个简单的socket服务器

#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main()
{
int sockfd = 0;
int connfd = 0;
int ret = -1;
sockfd = socket(AF_INET, SOCK_STREAM, 0);       /* 创建socket */
if( -1 == sockfd )
{
perror("func socket() error!");
return 0;
}

struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(4444);   		/* 设置监听的端口 */
addr.sin_addr.s_addr = inet_addr("127.0.0.1");    /* 绑定的地址 */

if(-1 == bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) )     /* 绑定地址 */
{
perror("func bind() error!");
return 0;
}

if(-1 == listen(sockfd, 10))           /* 监听 */
{
perror("func listen() error!");
return 0;
}

struct sockaddr_in client_addr;      /* 用于保存客户端的地址信息 */
memset(&client_addr, 0, sizeof(client_addr));
socklen_t client_len = sizeof(client_addr);
connfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);    /* 获取一个链接 */
if(-1 == connfd)
{
perror("func accept() error~");
exit(0);
}

printf("client %s connected.\n", inet_ntoa(client_addr.sin_addr));

char buff[100];				/* 用于接收和发送数据 */
memset(buff, 0, sizeof(buff));
ret = recv(connfd, buff, sizeof(buff), 0);      /* 接收数据,返回接收的数据长度,等于0表示对方已关闭 */
if(ret < 0)
{
perror("func recv() error!");
close(connfd);
close(sockfd);
return 0;
}
else if(0 == ret)
{
printf("peer has closed.\n");
close(connfd);
close(sockfd);
return 0;
}
else
printf("recv: %s\n", buff);

ret = write(connfd, buff, strlen(buff));     /* 发送数据,Linux上一切设备皆文件,顾所有的操作都能以文件的形式完成,成功返回发送的长度 */
if(ret < 0)
{
perror("func write() error!");
}

close(connfd);
close(sockfd);
return 0;
}


参考文献:http://blog.csdn.net/yueguanghaidao/article/details/7035248?ticket=ST-74446-QWLN73sAGSZp7dFOBpul-passport.csdn.net
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: