一、TCP服务器编写流程
服务器:
创建套接字 socket()
将套接字与服务器网络信息结构体绑定 bind()
将套接字设置为监听状态 listen()
阻塞等待客户端的连接请求 accept()
进行通信 recv()/send()
关闭套接字 close()
二、TCP编程——socket函数
头文件
#include <sys/types.h>
#include <sys/socket.h>
函数:
int socket(int domain, int type, int protocol);
功能:创建一个套接字,返回一个文件描述符
参数:
domain:通信域,协议族
AF_UNIX 本地通信AF_INET ipv4网络协议
AF_INET6 ipv6网络协议
AF_PACKET 底层接口
type :套接字的类型
SOCK_STREAM 流式套接字(tcp)
SOCK_DGRAM 数据报套接字(udp)
SOCK_RAW 原始套接字(用于链路层)
protocol:附加协议,如果不需要,则设置为0
返回值:
成功:文件描述符
失败:‐1
三、 TCP编程——bind函数
头文件:
#include <sys/types.h>
#include <sys/socket.h>
函数;int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:将套接字与网络信息结构体绑定
参数:
sockfd:文件描述符,socket的返回值
addr:网络信息结构体
struct sockaddr 通用结构体(一般不用)
sockaddr_in 常用网络信息结构体
addrlen:addr的长度
返回值:
成功:0
失败:‐1
sockaddr_in 常用网络信息结构体
头文件:
#include <netinet/in.h>
函数结构体:
struct sockaddr_in
{
sa_family_t sin_family; //协议族 2字节
in_port_t sin_port; //端口号 2字节
struct in_addr sin_addr; //ip地址 4字节
char sin_zero[8] //填充,不起什么作用 8字节
};struct in_addr
{
in_addr_t s_addr; //ip地址 4字节
};
示例:
unsigned short port =8080;
struct sockaddr_in mysockaddr;
mysockaddr.sin_family = AF_INET;
mysockaddr.sin_port = htons(port);
mysockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sockfd,(struct sockaddr *)&mysockadrr,sizeof(mysockaddr)==-1)
{
perror("fail to bind");
exit(1);
}
四、 TCP编程——listen函数
头文件:
#include <sys/types.h>
#include <sys/socket.h>
函数:int listen(int sockfd, int backlog);
功能:将套接字设置为被动监听状态,这样做之后就可以接收到连接请求
参数:
sockfd:文件描述符,socket函数返回值
backlog:允许同时通信连接的主机个数,一般设置为5、10
返回值:
成功:0
失败:‐1
五、TCP编程——accept函数
头文件:
#include <sys/types.h>
#include <sys/socket.h>
函数:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:阻塞等待客户端的连接请求
参数:
sockfd:文件描述符,socket函数的返回值
addr:接收到的客户端的信息结构体(自动填充,定义变量即可)
addrlen:addr的长度
返回值:
成功:新的文件描述符(只要有客户端连接,就会产生新的文件描述符,
这个新的文件描述符专门与指定的客户端进行通信的)
失败:‐1
注意:返回的是一个已连接套接字,这个套接字代表当前这个连接
5.1、分析功能
六、TCP服务器代码实现并且(与上一节TCP客户端)通信
6.1、简单的服务器代码
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include<stdlib.h>
#include <unistd.h>
#include<string.h>
int main(int argc ,char *argv[])
{
if(argc <3)
{
printf("error: lose ip port\n");
exit(1);
}
int sockfd ;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("fail to sockfd");
exit(1);
}
struct sockaddr_in mysockaddr;
mysockaddr.sin_family=AF_INET;
mysockaddr.sin_port=htons(atoi(argv[2]));
mysockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
socklen_t addrlen = sizeof(mysockaddr);
if(bind(sockfd,(struct sockaddr*)&mysockaddr,addrlen)==-1)
{
perror("fail to bind");
exit(1);
}
if(listen(sockfd,10)==-1)
{
perror("fail to listen");
exit(1);
}
int acceptfd;
struct sockaddr_in acceptaddr;
socklen_t acceptlen=sizeof(acceptaddr);
if((acceptfd= accept(sockfd,(struct sockaddr *)&acceptaddr,&acceptlen))==-1)
{
perror("fail to acceptfd");
exit(1);
}
char buf[128]="";
char text[128]="";
if(recv(acceptfd,buf,128,0)==-1)
{
perror("fail to recv");
exit(1);
}
printf("ip=%s,port=%d\n",inet_ntoa(acceptaddr.sin_addr),ntohs(acceptaddr.sin_port));
printf("%s\n",buf) ;
strcat(text, " *_*");
if(send(acceptfd,text,128,0)==-1)
{
perror("fail to send");
exit(1);
}
close(acceptfd);
close(sockfd);
return 0;
}
6.2、简单的客户端代码
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define N 1024
int main(int argc ,char *argv[])
{
if(argc<3)
{
printf("fail ,lose ip port\n");
exit(1);
}
int sockfd;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("fail to sockfd");
exit(1);
}
// printf("TCP:sockfd= %d\n",sockfd);
struct sockaddr_in mysockaddr;
mysockaddr.sin_family=AF_INET;
mysockaddr.sin_port=htons(atoi(argv[2]));
mysockaddr.sin_addr.s_addr=inet_addr(argv[1]);
socklen_t addrlen= sizeof(mysockaddr);
if(connect(sockfd,(struct sockaddr*)&mysockaddr,addrlen)==-1)
{
perror("fail to connect");
exit(1);
}
char buf[N]="";
fgets(buf,N,stdin);
if(send(sockfd,buf,N,0)==-1)
{
perror("fail to send");
exit(1);
}
char text[500]="";
if(recv(sockfd,text,50,0)==-1)
{
perror("fail to recv");
exit(1);
}
printf("from server: %s\n",text);
close(sockfd);
return 0;
}
运行结果