相关函数
int socket(int domain,int type,int protocol);
参数:
domain:
AF_INET
AF_INET6
AF_UNIX,AF_LOCAL
AF_NETLINK
AF_PACKET
type:
SOCK_STREAM: 流式套接字,唯一对应于TCP
SOCK_DGRAM:数据报套接字,唯一对应着UDP
SOCK_RAW:原始套接字
protocol:
一般填0,原始套接字编程时需填充
返回值
成功返回文件描述符
出错返回-1
如果是IPV6编程,要使用struct sockddr_in6结构体(man 7 IPV6),通常使用struct sockaddr_storage来编程。
int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen)
参数
sockfd:通过socket()函数拿到的fd
addr:采用struct sockaddr的结构体地址,通用结构体
struct sockaddr{
sa_family_t sa_family;
char sa_data[4];
}
struct sockaddr_in{ 基于Internel通信结构体
as_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
sin_zero , //填充字节,需清零
}
struct in_addr{
uint32_t s_addr;
}
addrlen:地址长度
int listen(int sockfd,int backlog);
参数:
sockfd: 通过socket()函数拿到的fd;
backLog:同时允许几路客户端和服务器进行正在连接的过程(正在三次握手),一般填5。
返回值:
成功返回0
出错返回-1
listen(fd,5);//表示系统允许11(2*5+1)个客户端同时进行三次握手
阻塞等待客户端连接请求
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数
sockfd:经过前面socket()创建并通过bind(),listen()设置过的fd
addr:指向存放地址信息的结构体的首地址
获取客服端IP地址和端口号
addrlen:存放地址信息的结构体的大小
返回值
成功,返回返回已经建立连接的新的newfd
出错,返回-1
int connect (int sockfd, struct sockaddr * serv_addr, int addrlen)
参数:
sockfd
1.socket函数创建一个(监听)套接字
2.bind函数给套接字绑定地址(IP + Port)。即给套接字提高网络连接路口
3.listen函数将套接字设置为监听状态,相当于将手机设置为待机状态。调用listen 函数实现。
4.accept函数阻塞接收客户端连接。
5.收发数据,调用 send/write 和 recv/read 函数实现。
6.调用 close 函数实现关闭客服端连接。
tcp_ser.c
#include
#include
#include
#include
#include
#include
#include
#include #define SERV_PORT 8888
#define SERV_IP_ADDR "192.168.11.128"
#define BACKLOG 5
#define BUFSIZE 1024
#define QUIT_STR "QUIT"
int main()
{int sockfd;//1.创建套接字sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd<0){perror("socket");exit(1);}//2.给套接字绑定地址struct sockaddr_in myaddr;//清零myaddr结构体里的数据bzero(&myaddr,sizeof(myaddr));//初始化myaddr结构体myaddr.sin_family=AF_INET; //协议簇myaddr.sin_port=htons(SERV_PORT); //指定端口,主机字节序转换为网络字节序myaddr.sin_addr.s_addr=inet_addr(SERV_IP_ADDR);//指定IP地址,将字符串转为无符号整型//inet_pton(AF_INET,SERV_IP_ADDR,(void *)myaddr.sin_addr_s_addr);int ret=bind(sockfd,(struct sockaddr *)&myaddr,sizeof(myaddr));if(ret ==-1){perror("bind");exit(2);}//3.使套接字能够监听,能够被其他客服端连接int res_lis=listen(sockfd,BACKLOG);if(res_lis==-1)//表示系统允许11(2*5+1)个客户端同时进行三次握手{perror("listen");//exit(3);}char buff[BUFSIZE];//4.阻塞等待接受客服端连接struct sockaddr_in saddr;bzero(&saddr,sizeof(saddr));//等待连接socklen_t length = sizeof(saddr);int newfd=accept(sockfd,(struct sockaddr *)&saddr,&length);if(newfd<0){perror("accept");exit(5);}while(1){memset((void *)buff,0,1024);int ret2=read(newfd,buff,sizeof(buff));if(ret2<=0){break;}/*int ret2=recv(newfd,buff,BUFSIZE-1,0);if(ret2==0){ break;}*/printf("receive data is %s\n",buff);//判断是否接受到的数据是不是QUIT_STR,是的话,就退出此次循环if(!strncasecmp(buff,QUIT_STR,strlen(QUIT_STR))){printf("client is exiting\n");break;}}close(newfd);close(sockfd);return 0;
}
1.socket函数创建一个套接字。
2.(可以绑定也可以不绑定)bind函数给套接字绑定地址,如果没有绑定,系统将自动给套
接字分配地址。
3.connect函数连接服务器。
4.收发数据,调用 send/write 和 recv/read 函数实现。
5.close函数断开连接
tcp_cli.c
#include
#include
#include /* See NOTES */
#include
#include
#include
#include
#include #define SERV_PROT 8888
#define SERV_IP_ADDR "192.168.11.128"
#define BUFSZIE 1024
#define QUIT_STR "QUIT"
int main()
{int sockfd;//1.创建一个套接字sockfd=socket(AF_INET,SOCK_STREAM,0);//2.不调bind函数来给套接字绑定地址,由系统自动分配//3.连接服务器件struct sockaddr_in saddr;saddr.sin_family=AF_INET;saddr.sin_port=htons(SERV_PROT);saddr.sin_addr.s_addr=inet_addr(SERV_IP_ADDR);if(connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr)) == -1){perror("connect");exit(1);}char buffer[1024];while(1){memset(buffer,0,1024);if(fgets(buffer,1024,stdin)==NULL){continue;}send(sockfd,buffer,sizeof(buffer),0);if(!strncasecmp(buffer,QUIT_STR,strlen(QUIT_STR))){break;}}close(sockfd);return 0;
}
客户端向服务端发送数据,当发送数据为quit时,就服务端和客服端的连接。