int socket(int domain, int type, int protocol);
Name | Purpose | Man page |
---|---|---|
AF_INET | IPv4 Internet protocols | ip(7) |
AF_INET6 | IPv6 Internet protocols | ipv6(7) |
AF_UNIX / AF_LOCAL | Local communication | unix(7) |
Name | Purpose |
---|---|
SOCK_STREAM | 流式套接字,唯一对应着TCP |
SOCK_DGRAM | 数据报套接字,唯一对应着UDP |
SOCK_RAW | 原始套接字 |
protocol
一般填0,原始套接字编程时需要填充
返回值
成功时,将返回新套接字的文件描述符。
错误返回错误-1,并设置errno。
int bind(int sockfd, const struct sockaddr addr, socklen_t addrlen);
头文件
#include
#include
sockfd是由socket()返回的文件描述符
addr是指向 struct sockaddr的结构体变量的地址
addrlen 地址长度
返回值
成功时,将返回0。
错误返回错误-1,并设置errno。
struct sockaddr是通用结构体,对于不同的协议有不同的结构体
AF_INET对应的struct sockaddr_in结构体:
1)定义一个struct sockaddr_in类型的变量并清空
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
2)填充地址信息
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(8888);
myaddr.sin_addr.s_addr = inet_addr("192.168.1.100");
3)将该变量强制转换为struct sockaddr类型在函数中使用
bind(lsockfd, (struct sockaddr*)(&myaddr), sizeof(myaddr));
1)unsigned long inet_addr(char address);
address是以‘\0’结尾的点分IPV4字符串。该函数返回32位的地址。如果字符串包含的不是合法的IP地址,则函数返回-1.
例如:
struct in_addr addr;
addr.s_addr = inet_addr("192.168.1.100");
2)char inet_ntoa(struct in_addr address);
address是IPv4结构地址,函数返回指向包含点分IP地址的静态存储区字符指针。如果错误则返回NULL
int connect(int sockfd, const struct sockaddr addr, socklen_t addrlen);
头文件
#include
#include
sockfd是由socket()返回的文件描述符
addr服务端的地址信息
addrlen 地址长度
返回值
成功时,将返回0。
错误返回错误-1,并设置errno。
connect()是客户端使用的系统调用
int listen(int sockfd, int backlog);
int accept(int sockfd, struct sockaddr * addr, socklen_t addrlen) ;
头文件
#include
#include
sockfd: 监听套接字
addr:对方地址
addrlen:地址长度
返回值
成功时返回已经建立好连接的套接字。
失败返回-1。
listen()和accept()是TCP服务端使用的函数。
ssize_t recv(int sockfd, void buf, size_t len, int flags);
头文件
#include
#include
buf:发送缓冲区首地址
len:发送的字节数
flags:接受方式(通常为0)
返回值
成功时返回实际接收的字节数
失败返回-1,并设置errno
ssize_t read(int fd, void buf, size_t count);
ssize_t recvfrom(int sockfd, void buf, size_t len, int flags, struct sockaddr src_addr, socklen_t addrlen);
ssize_t send(int socket, const void buffer, size_t length, int flags);
该函数于recv()组合使用
ssize_t write(int fd, const void buf, size_t count);
该函数于read()组合使用
ssize_t recvfrom(int socket, void buffer, size_t length, int flags, struct sockaddr address, socklen_t address_len);
该函数于recvfrom()组合使用。
1)int close(int fd);
功能:关闭双向通信
2) int shutdown(int sockfd , int howto);
TCP循环服务器一次只能处理一个客户端的请求.只有在这个客户的所有请求都满足后, 服务器才可以继续后面的请求.这样如果有一个客户端占住服务器不放时,其它的客户机都不能工作了.因此,TCP服务器一般很少用循环服务器模型的.
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
int sockfd;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket");
exit(-1);
}
struct sockaddr_in myaddr;
memset(&myaddr,0,sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(8888);
myaddr.sin_addr.s_addr = inet_addr("192.168.9.10");
bind(sockfd,(struct sockaddr*)(&myaddr),sizeof(myaddr));
listen(sockfd,1);
struct sockaddr_in caddr;
int cfd;
socklen_t len=sizeof(caddr);
char buf[20];
while(1)
{
cfd=accept(sockfd,(struct sockaddr*)(&caddr),&len);
read(cfd,buf,20);
printf("%s\n",buf);
close(cfd);
}
close(sockfd);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void signal_handler(int signo)
{
if(sogno == SIGCHLD)
{
wait(NULL);
}
}
int main(int argc, const char *argv[])
{
int sfd;
signal(SIGCHLD,signal_handler);
sfd=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in myaddr;
memset(&myaddr,0,sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(8888);
myaddr.sin_addr.s_addr = inet_addr("192.168.9.10");
bind(sfd,(struct sockaddr *)(&myaddr),sizeof(myaddr));
listen(sfd,10);
struct sockaddr_in caddr;
socklen_t len = sizeof(caddr);
int cfd;
char buf[20];
char buffer[]={"stop"};
pid_t pid;
while(1)
{
cfd=accept(sfd,(struct sockaddr*)(&caddr),&len);
if(cfd == -1)
{
perror("accept");
exit(-1);
}
pid=fork();
if(pid==0)
{
close(sfd);
printf("client is connect ,sockfd is %d\n",cfd);
while(1)
{
read(cfd,buf,20);
if(strcmp(buf,buffer) == 0)
{
printf("client is quit,sockfd is %d !\n",cfd);
break;
}
printf("%s\n",buf);
}
exit(0);
}
close(cfd);
}
close(sfd);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void pthread_handle(void * arg);
int main(int argc, const char *argv[])
{
int sfd;
sfd=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in myaddr;
myaddr.sin_family=AF_INET;
myaddr.sin_port = htons(8888);
myaddr.sin_addr.s_addr = inet_addr("192.168.9.10");
bind(sfd,(struct sockaddr*)(&myaddr),sizeof(myaddr));
listen(sfd,10);
struct sockaddr_in caddr;
socklen_t len = sizeof(caddr);
int cfd;
pthread_t pfd;
while(1)
{
cfd=accept(sfd,(struct sockaddr*)(&caddr),&len);
if(cfd == -1)
{
perror("accept");
exit(0);
}
char ipv4_addr[16];
if(!inet_ntop(AF_INET,(void *)&caddr.sin_addr,ipv4_addr,sizeof(caddr)))
{
perror("inet_ntop");
exit(1);
}
printf("client is connect,addr is %s \n",ipv4_addr);
pthread_create(&pfd,NULL,pthread_handle,(void*)&cfd);
pthread_join(pfd,NULL);
}
close(sfd);
return 0;
}
void pthread_handle(void * arg)
{
char buf[20];
char buffer[]="stop";
int cfd = *(int *)arg;
while(1)
{
read(cfd,buf,20);
printf("%s\n",buf);
if(strcmp(buf,buffer)==0)
{
printf("client is quit,cfd is %d\n",cfd);
break;
}
}
close(cfd);
}