此程序代碼中不包含併發。併發服務器在後續博客陸續推出
程序框圖如下:
server.c
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdlib.h>
#include <string.h>
#define PORT 8888
void sys_err(const char * str)
{
perror(str);
exit(-1);
}
int main()
{
//參數1:IPV4
//參數2:流式協議
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1)
{
perror("socket error");
exit(-1);
}
//端口複用
int opt = 1;
int ret = setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
if(ret == -1)
{
sys_err("setsockopt error");
}
//bind綁定ip和端口
struct sockaddr_in ser_addr;
memset(&ser_addr,0,sizeof(ser_addr));
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(PORT);
ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
ret = bind(sockfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
if(ret == -1)
{
sys_err("bind error");
}
//設置監聽上限
ret = listen(sockfd,128);
if(ret == -1)
{
sys_err("listen error");
}
printf("accept connecting.....\n");
struct sockaddr_in cli_addr;
socklen_t cli_addr_len = sizeof(ser_addr);
char str[BUFSIZ];
memset(str,0,sizeof(str));
char buf[1024];
memset(buf,0,sizeof(buf));
int rbytes = 0;
int wbytes = 0;
int i = 0;
//阻塞等帶客戶端連接
int connfd = accept(sockfd,(struct sockaddr *)&cli_addr,&cli_addr_len);
if(connfd == -1)
{
sys_err("accept error");
}
while(1)
{
rbytes = read(connfd,buf,sizeof(buf));
if(read < 0)
{
sys_err("read error");
}
else if(rbytes == 0)
{
close(connfd);
return 0;
}
else
{
for(i = 0;i<rbytes;i++)
{
buf[i] = toupper(buf[i]);
}
}
write(STDOUT_FILENO,buf,rbytes);
wbytes = write(connfd,buf,rbytes);
sleep(1);
}
close(sockfd);
return 0;
}
client.c
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdlib.h>
#include <string.h>
#define PORT 8888
void sys_err(const char * str)
{
perror(str);
exit(-1);
}
int main()
{
//socket建立通信
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1)
{
perror("socket error");
exit(-1);
}
//客戶端與服務器建立連接
struct sockaddr_in ser_addr;
memset(&ser_addr,0,sizeof(ser_addr));
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(PORT);
inet_pton(AF_INET,"127.0.0.1",&ser_addr.sin_addr);
int ret = connect(sockfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
if(ret == -1)
{
sys_err("connect error");
}
char buf[1024];
memset(buf,0,sizeof(buf));
int wbytes = 0;
int rbytes = 0;
while(1)
{
fgets(buf,sizeof(buf),stdin);
wbytes = write(sockfd,buf,strlen(buf));
if(wbytes < 0)
{
sys_err("read error");
}
else if(wbytes == 0)
{
close(sockfd);
return 0;
}
rbytes = read(sockfd,buf,sizeof(buf));
if(rbytes < 0)
{
sys_err("read error");
}
wbytes = write(STDOUT_FILENO,buf,rbytes);
if(wbytes != rbytes)
{
sys_err("write error");
}
}
close(sockfd);
return 0;
}
總結:此篇博客只是簡單熟悉一下socket 通信的API,後續將有併發中select,poll,epoll 以及線程池的併發服務器的博客相繼退出。