相关函数
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
文章目录
- TCP服务端实现步骤:
- TCP服务端代码
- TCP 客户端实现步骤:
- TCP 客户端代码
- 执行结果
TCP服务端实现步骤:
1.socket函数创建一个(监听)套接字
2.bind函数给套接字绑定地址(IP + Port)。即给套接字提高网络连接路口
3.listen函数将套接字设置为监听状态,相当于将手机设置为待机状态。调用listen 函数实现。
4.accept函数阻塞接收客户端连接。
5.收发数据,调用 send/write 和 recv/read 函数实现。
6.调用 close 函数实现关闭客服端连接。
TCP服务端代码
tcp_ser.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#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;
}
TCP 客户端实现步骤:
1.socket函数创建一个套接字。
2.(可以绑定也可以不绑定)bind函数给套接字绑定地址,如果没有绑定,系统将自动给套
接字分配地址。
3.connect函数连接服务器。
4.收发数据,调用 send/write 和 recv/read 函数实现。
5.close函数断开连接
TCP 客户端代码
tcp_cli.c
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <stdlib.h>
#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时,就服务端和客服端的连接。