1.TCP客户/服务器模型
2.回射客户/服务器
3.socket函数
头文件:<sys/socket.h>
功能:创建一个套接字用于通信
原型:int socket(int domain, int type, int protocol);
参数:domain:指定通信协议族(protocol family)
type:指定socket类型,流式套接字SOCK_STREAM,数据报套接字SOCK_DGRAM,原始套接字SOCK_RAW
protocol:协议类型
返回值:成功返回非负整数,它与文件描述符类似,我们把它称为套接口描述字,简称套接字。失败返回-1。
4. bind函数
头文件:<sys/socket.h>
功能:绑定一个本地地址到套接字
原型:int bind(int sockfd, const struct sockaddr* addr, soclen_taddrlen);
参数: sockfd:socket函数返回的套接字
addr:要绑定的地址
addrlen:地址长度
返回值:成功返回0,失败返回-15. listen函数
主动套接字:发起连接connect
被动套接字:接受连接accept
头文件:#include <sys/socket.h>
功能:将套接字用于监听进入的连接
原型:int listen(int sockfd, int backlog);
参数:sockfd:socket函数返回的套接字
backlog:规定内核为此套接字排队的最大连接个数
返回值:成功返回0,失败返回-1
一般来说,listen函数应该在调用socket和bind函数之后,调用函数accept之前调用。
对于给定的监听套接口,内核要维护两个队列:
1. 已由客户发出并到达服务器,服务器正在等待完成相应的TCP三路握手过程
2. 已完成连接的队列
6.accept函数
头文件:<sys/socket.h>
功能:从已完成连接队列返回第一个连接,如果已完成连接队列为空,则阻塞。
原型:int accept(intsockfd, struct sockaddr* addr, socklen_t* addrlen);
参数:sockfd:服务器套接字
addr:将返回对等方的套接字地址
addrlen:返回对等方的套接字地址长度
返回值:成功返回非负整数,失败返回-17. connect函数
头文件:<sys/socket.h>
功能:建立一个连接至addr所指定的套接字
原型:int connect(int sockfd, const structsockaddr* addr, socklen_t addrlen);
参数:sockfd:未连接套接字
addr:要连接的套接字地址
addrlen:第二个参数addr长度
返回值:成功返回0,失败返回-1
8.示例
echoserver.cpp
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0)
int main () {
int listenfd;
if(( listenfd= socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
//if((listenfd= socket(PF_INET, SOCK_STREAM, 0)) <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 = htonl(INADDR_ANY);
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//inet_aton("127.0.0.1", &servaddr.sin_addr);
if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr))<0)
ERR_EXIT("bind");
if(listen(listenfd, SOMAXCONN) < 0)
ERR_EXIT("listen");
struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
int conn;
if((conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0)
ERR_EXIT("accept");
char recvbuf[1024];
while(1) {
memset(recvbuf, 0, sizeof(recvbuf));
int ret = read(conn, recvbuf, sizeof(recvbuf));
fputs(recvbuf, stdout);
write(conn, recvbuf, ret);
}
close(listenfd);
close(conn);
return 0;
}
echoclient.cpp
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define EXIT_FALURE 1
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FALURE); \
}while(0)
int main () {
int sock;
if(( sock= socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
ERR_EXIT("socket");
sock = socket(PF_INET, SOCK_STREAM, 0);
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");
if(connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
ERR_EXIT("connect");
char sendbuf[1024] = {0};
char recvbuf[1024] = {0};
while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) {
write(sock, sendbuf, strlen(sendbuf));
memset(sendbuf, 0, sizeof(sendbuf));
memset(recvbuf, 0, sizeof(recvbuf));
int ret = read(sock, recvbuf, sizeof(recvbuf));
fputs(recvbuf, stdout);
}
close(sock);
return 0;
}