TCP客户/服务器模型
服务器模型:
回射客户/服务器
(1)、创建套接字
功能:创建一个套接字用于通信
函数声明:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);参数:- domain:指定通信协议族(protocol family)
- type:指定socket类型,流式套接字SOCK_STREAM,数据报套接字SOCK_DGRAM,原始套接字SOCK_RAW
- protocol:协议类型
成功返回非负整数,
它与文件描述符类似,我们把它称为套接口描述字,简称套接字。失败返回-1
(2)、绑定地址
功能:绑定一个本地地址到套接字
函数声明:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);参数:- sockfd:socket函数返回的套接字
- addr:要绑定的地址
- addrlen:地址长度
返回值:
成功返回0,失败返回-1
(3)、监听连接
(3)、监听连接
功能:将套接字用于监听进入的连接
函数声明:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
函数参数:- sockfd:socket函数返回的套接字
- backlog:规定内核为此套接字排队的最大连接个数
返回值:
成功返回0,失败返回-1
成功返回0,失败返回-1
一般来说,listen函数应该在调用socket和bind函数之后,调用函数accept之前调用。
对于给定的监听套接口,内核要维护两个队列:
1>已由客户发出并到达服务器,服务器正在等待完成相应的TCP三路握手过程
2>已完成连接的队列(4)、接收连接
函数声明:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);函数参数:- sockfd:服务器套接字
- addr:将返回对等方的套接字地址
- addrlen:返回对等方的套接字地址长度
返回值:
成功返回非负整数,失败返回-1
(5)、建立连接
(5)、建立连接
函数声明:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);函数参数:- sockfd:未连接套接字
- addr:要连接的套接字地址
- addrlen:第二个参数addr长度
返回值:
成功返回0,失败返回-1
服务端echoserv:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m);\
exit(EXIT_FAILURE);\
}while(0)
int main()
{
int listenfd;
listenfd = socket(PF_INET,SOCK_STREAM,0);
if (listenfd < 0)
ERR_EXIT("socket");
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5188);
//servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
int ret;
ret = bind(listenfd,(struct sockaddr*)&servaddr, sizeof(servaddr));
if (ret < 0)
ERR_EXIT("bind");
if(listen(listenfd,SOMAXCONN) < 0)
ERR_EXIT("listen");
struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
int conn;
char buf[1024];
conn = accept(listenfd,(struct sockaddr*)&peeraddr,&peerlen);
while(1)
{
int ret=read(conn,buf,1024);
write(conn,buf,sizeof(buf));
puts(buf);
}
return 0;
}客户端echocli.c:#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m);\
exit(EXIT_FAILURE);\
}while(0)
int main()
{
int conn;
char buf[1024];
if ((conn = socket(PF_INET,SOCK_STREAM,0)) < 0)
ERR_EXIT("socket");
struct sockaddr_in cliaddr;
memset(&cliaddr,0,sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
cliaddr.sin_port = htons(5188);
cliaddr.sin_addr.s_addr = htonl(INADDR_ANY);
connect(conn,(struct sockaddr*)&cliaddr,sizeof(cliaddr));
while(1)
{
gets(buf);
write(conn,buf,sizeof(buf));
read(conn,buf,1024);
puts(buf);
}
return 0;
}
本文深入探讨了TCP客户端和服务器的基本模型,包括创建套接字、绑定地址、监听连接、接收连接和建立连接的过程,并通过示例代码展示了服务器echoserv和客户端echocli的实现。
323

被折叠的 条评论
为什么被折叠?



