套接字socket:
服务器(6)
socket
bind(绑定)
listen(监听客户端,)
accept(接收)
send
recv
客户端(4)
socket
connect (发起连接时,端口号要保持一致)
send
recv
1、socket函数
int socket(int domain,int type,int protocol);
socket函数用于创建一个socket描述符,它是唯一表示标识一个
socket, sockfd
domain:叫做协议族/协议域。
常用的协议族有AF_INET(决定了要用IP v地址与端口号的组合),
AF_INET6,AF_LOCAL等等,协议族决定了socket的地址类型。
type:是指定socket的类型。常用的是:
SOCK_STREAM(流式套接字,使用的是TCP协议);
SOCK_DGRAM(数据包套接字,使用的是UDP协议);
protocol: 指定协议,通常情况下写成0即可
当我们调用了socket创建一个socket的时候,返回sockfd,并没有一个
具体的地址,如果我们想给socket赋值一个地址的话,我们必须调用
bind()函数,否则,调用listen()connect()函数时,系统会自动随机分配
一个端口
2、bind()绑定
bind()函数就是把地址族中的特定地址赋值给socket,
AF_INET就是把IP v4的地址和端口号赋值给了socket,
int bind(int sockfd,const struct sockaddr * my_addr,socklen_t addrlen);
sockfd:socket描述字符,是通过socket函数创建的,bind()函数就是
给这个描述字绑定一个名字。
addr:是指向要绑定给sockfd的协议地址
addrlen:对应是地址的长度
出现无法绑定的问题:
setsockopt:函数的用处就是解决套接字绑定失败。
int setsockopt(int s,int level,int optname,const void* optval,socklen_t optlen);
s:标识的是一个套接字的描述符
level:选项定义的层次,SOL_SOCKET,IPPROTO_TCP
optname:
optval:指向的是存放选项值的缓冲区
optlen:
3、listen()监听-----服务器使用,用于监听sockfd
int listen(int sockfd,int backlog);
listen(sockfd,5);在监听队列里放5个客户端,并不代表总共只能监听5个客户端
backlog:相应的socket可以排列的最大链接数。
4、connect()连接------只用于客户端,来连接服务器
int connect(int sockfd,const struct sockaddr * serv_addr,socklen_t addrlen)
sockfd:就是客户端的socket描述字
serv_addr:服务器的socket地址
addrlen:socket地址的长度
5、accept()
int accept(int sockfd,const struct sockaddr * addr,socklen_t *addrlen)
TCP服务器调用socket(),bind(),listen()
TCP客户端依次调用socket(),connect(),
TCP服务器监听到这个客户端的连接请求后,就会调用accept()函数来接收请求,
这样连接就建立完成。
sockfd:服务器的socket描述字
addr:用于返回客户端的协议地址,
addrlen:这个协议地址的长度?为什么是指针
当accept成功之后,返回值就是会长生一个新的描述字,代表客户端连接服务器成功。
6、 read()从fd中读取数据,write()写数据
recv() send()
recvfrom() sendto()
服务器端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#define PORT 8888
int main()
{
int sockfd, ret;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("socket");
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("192.168.1.10");
ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (-1 == ret)
{
perror("bind");
exit(1);
}
ret = listen(sockfd, 5);
if (-1 == ret)
{
perror("listen");
exit(1);
}
int fd[1000] = {0};
int MaxFd, i = 0, j;
fd_set ReadFd, tmpfd;
char buf[32] = {0};
int length = sizeof(client_addr);
FD_ZERO(&ReadFd);
FD_SET(sockfd, &ReadFd);
MaxFd = sockfd;
while (1)
{
tmpfd = ReadFd;
ret = select(MaxFd + 1, &tmpfd, NULL, NULL, NULL);
if (-1 == ret)
{
perror("select");
}
if (FD_ISSET(sockfd, &tmpfd)) //有客户端发起连接
{
for (j = 0; j < i; j++)
{
if (fd[j] == 0)
{
break;
}
}
fd[j] = accept(sockfd, (struct sockaddr *)&client_addr, &length);
if (-1 == fd[j])
{
perror("accept");
}
printf("accept client %d port %d\n", fd[j], client_addr.sin_port);
if (MaxFd < fd[j])
{
MaxFd = fd[j];
}
FD_SET(fd[j], &ReadFd);
if (j == i)
{
i++;
}
}
else //有客户端发消息
{
for (j = 0; j < i; j++)
{
if (FD_ISSET(fd[j], &tmpfd))
{
ret = recv(fd[j], buf, sizeof(buf), 0);
if (-1 == ret)
{
perror("recv");
}
if (!strcmp(buf, "bye"))
{
close(fd[j]);
FD_CLR(fd[j], &ReadFd); //从集合里面清除
fd[j] = 0;
break;
}
printf("%s\n", buf);
memset(buf, 0, sizeof(buf));
break;
}
}
}
}
return 0;
}
客户端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#define PORT 8888
int sockfd;
void StopClient(int num) //进程收到SIGINT信号,退出
{
send(sockfd, "bye", strlen("bye"), 0);
close(sockfd);
printf("BYE!\n");
exit(1);
}
int main()
{
int ret;
struct sockaddr_in server_addr;
signal(SIGINT, StopClient);
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("socket");
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("192.168.1.10");
ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (-1 == ret)
{
perror("connect");
exit(1);
}
char buf[32] = "helloworld";
while (1)
{
ret = send(sockfd, buf, strlen(buf), 0);
if (-1 == ret)
{
perror("send");
exit(1);
}
sleep(1);
}
return 0;
}