服务器端代码
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<strings.h>
#include<sys/wait.h>
#include<string.h>
#include<errno.h>
#define DEFAULT_PORT 6666
int main(int argc, char** argv)
{
int serverfd, acceptfd;
struct sockaddr_in my_addr; //服务端
struct sockaddr_in their_addr; //客户端
unsigned int sin_size, myport = 6666, lisnum = 10;
if((serverfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
return -1;
}
printf("socket ok \n");
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(DEFAULT_PORT);
//指定地址为0.0.0.0即为任意地址,内核在套接字已连接或者在套接字上发送数据时才选择本地地址
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 0);
//将本地地址和套接字绑定
if(bind(serverfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) == -1)
{
perror("bind");
return -2;
}
printf("bind ok \n");
//监听服务器套接字
if(listen(serverfd, lisnum) == -1)
{
perror("listen");
return -3;
}
printf("listen ok \n");
fd_set client_fdset;
int maxsock;
struct timeval tv;
int client_sockfd[5];
//客户端的套接字数组初始化为0
bzero((void*) client_sockfd, sizeof(client_sockfd));
int conn_amount = 0;
maxsock = serverfd;
char buffer[1024];
int ret = 0;
while(1)
{
//fd 集合不能复用 每次轮寻都要重新设置
FD_ZERO(&client_fdset);
FD_SET(serverfd, &client_fdset);//将serverfd 加入 client_fdset集合
tv.tv_sec = 100;//设置超时时间
tv.tv_usec = 0;
for(int i = 0; i<5; i++)
{
if(client_sockfd[i]!=0)
{
FD_SET(client_sockfd[i], &client_fdset);
}
}
//阻塞函数 直到某个IO有数据才继续往下执行
ret = select(maxsock+1, &client_fdset, NULL, NULL, &tv);
if(ret<0)
{
perror("select error!\n");
break;
}
else if(ret == 0)
{
printf("timeout!\n");
continue;
}
for(int i = 0; i<conn_amount; i++)
{
if(FD_ISSET(client_sockfd[i], &client_fdset))
{
printf("start recv from client[%d]:\n, i");
//使用TCP从另一端接收收据 1024是缓冲区大小
ret = recv(client_sockfd[i], buffer, 1024, 0);
if(ret<0)
{
printf("client[%d] close\n", i);
close(client_sockfd[i]);
FD_CLR(client_sockfd[i], &client_fdset);
client_sockfd[i] = 0;
}
else
printf("recv from client[%d]:%s\n", i, buffer);
}
}
if(FD_ISSET(serverfd, &client_fdset))
{
struct sockaddr_in client_addr; //新的客户端连接
size_t size = sizeof(struct sockaddr_in);
//accept 被调用时,为该请求产生一个新的Socket,并把这个请求从监听队列中剔除 client_addr 是一个描述socket
//信息的结构 不过它是一个空容器用来存储接收到的client 的 ip port 等信息
//sock_client返回这个新的文件描述符(socket),以后和client 交谈的就是这个新的socket
int sock_client = accept(serverfd, (struct sockaddr*)(&client_addr), (unsigned int*)(&size));
if(sock_client<0)
{
perror("accept error!\n");
continue;
}
if(conn_amount<5)
{
client_sockfd[conn_amount++] = sock_client;
bzero(buffer, 1024);
strcpy(buffer, "this is a server! welcome!\n");
send(sock_client, buffer, 1024, 0); //把内容传给新来的客户端
printf("new connection client[%d] %s:%d\n", conn_amount, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
bzero(buffer, sizeof(buffer));
ret = recv(sock_client, buffer, 1024, 0);
if(ret<0)
{
perror("recv error!\n");
close(serverfd);
return -1;
}
printf("recv : %s\n", buffer);
if(maxsock<sock_client)
maxsock = sock_client;
else
{
printf("max connections!!!quit!!\n");
break;
}
}
}
}
for(int i = 0; i<5; i++)
{
if(client_sockfd[i]!=0)
close(client_sockfd[i]);
}
close(serverfd);
return 0;
}
客户端代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<errno.h>
#define DEFAULT_PORT 6666
int main(int argc, char* argv[])
{
int connfd = 0;
int cLen = 0;
struct sockaddr_in client;
if(argc<2)
{
printf("Uasge: clientent[server IP address]\n");
return -1;
}
client.sin_family = AF_INET;
client.sin_port = htons(DEFAULT_PORT);
client.sin_addr.s_addr = inet_addr(argv[1]);
connfd = socket(AF_INET, SOCK_STREAM, 0);
if(connfd<0)
{
perror("socket");
return -1;
}
//从客户端连向server 包含了server 的ip地址
if(connect(connfd, (struct sockaddr*)&client, sizeof(client))<0)
{
perror("connect");
return -1;
}
char buffer[1024];
bzero(buffer, sizeof(buffer));
//使用TCP从另一端接收数据 1024是缓冲区大小
recv(connfd, buffer, 1024, 0);
printf("recv: %s\n", buffer);
bzero(buffer, sizeof(buffer));
strcpy(buffer, "this is a client!\n");
send(connfd, buffer, 1024, 0);
while(1)
{
bzero(buffer, sizeof(buffer));
scanf("%s", buffer);
int p = strlen(buffer);
buffer[p] = '\0';
send(connfd, buffer, 1024, 0);
printf("i have send buffer");
}
close(connfd);
return 0;
}
客户端先结束连接(ctrl+c),服务器进入死循环.