Liunx
/***************** server.c *******************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>//socket_in
#include <arpa/inet.h>
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
void ProcessConnect(int new_sock)
{
while(1)
{
char buf[1024] = {0};
ssize_t read_size = read(new_sock,buf,sizeof(buf)-1);
if(read_size < 0)
{
perror("read");
continue;
}
if(read_size == 0)//读到EOF 客户端断开连接
{
printf("[client %d] disconnect!\n",new_sock);
close(new_sock);
return;
}
buf[read_size] = '\0';
printf("[client %d] say %s\n",new_sock,buf);
write(new_sock,buf,strlen(buf));
}
}
int main(int argc,char* argv[])
{
if(argc != 3)
{
printf("Usage ./server [Ip] [port]\n");
return 1;
}
int listen_sock = socket(AF_INET,SOCK_STREAM,0);
if(listen_sock < 0)
{
printf("sock error");
return 1;
}
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(argv[1]);
addr.sin_port = htons(atoi(argv[2]));
int ret = bind(listen_sock,(sockaddr*)&addr,sizeof(addr));
if(ret <0)
{
printf("bind error");
return 1;
}
ret = listen (listen_sock,5);//内核最多允许多少客户等待
if(ret < 0)
{
printf("listen error");
return 1;
}
printf("Server start ok\n");
while(1)
{
sockaddr_in peer;
socklen_t len = 0;
//socklen_t len = sizeof(peer);
int new_sock = accept(listen_sock,(sockaddr*)&peer,&len);
if(new_sock < 0 )
{
perror("accept");
continue;
}
printf("[client %d] connect\n",new_sock);
ProcessConnect (new_sock);
}
close(listen_sock);
return 0;
}
/****************** client.c ********************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>//socket_in
#include <arpa/inet.h>//inet_addr
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
int main(int argc, char* argv[])
{
if(argc != 3)
{
printf("Usage ./server [ip] [port]\n");
return 1;
}
int sock = socket(AF_INET,SOCK_STREAM,0);
if(sock < 0 )
{
perror("socket");
return 1;
}
sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
server_addr.sin_port = htons(atoi(argv[2]));
int ret = connect(sock,(sockaddr*)&server_addr, sizeof(server_addr));
if(ret < 0)
{
printf("connect ");
return 1;
}
while(1)
{
printf(">begin>:");
fflush(stdout);
char buf[1024] = {0};
ssize_t read_size = read(0,buf,sizeof(buf)-1);
if(read_size < 0)
{
printf("read");
return 1;
}
if(read_size == 0)
{
printf("断开连接");
return 0;
}
buf[read_size] = '\0';
write(sock,buf,sizeof(buf));
char buf_output[1024] = {0};
read_size = read(sock,buf_output,sizeof(buf_output) - 1);
if(read_size < 0)
{
printf("read < 0");
return 1;
}
if(read_size == 0)
{
printf("read = 0");
}
buf_output[read_size] = '\0';
printf("server resp %s\n",buf_output);
}
return 0;
}
//为解决上边服务器只能单个客户端访问,以下客户端采用多进程方法改写
//此版本存在效率问题,相对于多线程的版本,后续会有IO多路复用,epool等
//从浅到深 编码风格不同 源于书写时间不同(未改以前)
/****************** server_fork.c *******************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
int ServerInit(char* ip,short port){
int listen_sock = socket(AF_INET,SOCK_STREAM,0);
if(listen_sock < 0){
printf("socket");
return -1;
}
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
int ret = bind(listen_sock,(sockaddr*)&addr,sizeof(addr));
if(ret < 0){
perror("bind");
return -1;
}
ret = listen(listen_sock,5);
if(ret < 0){
perror("listen");
return -1;
}
return listen_sock;
}
void ProcessConnect(int new_sock){
pid_t ret = fork();
if(ret < 0){
perror("fork");
return;
}
if(ret == 0){
while(1){
char buf[1024] = {0};
ssize_t read_size = read(new_sock,buf,sizeof(buf)-1);
if(read_size < 0){
perror("read");
exit(1);
}
if(read_size == 0){
printf("[client %d] disconnected! \n",new_sock);
close(new_sock);
exit(0);
}
buf[read_size] = '\0';
printf("[client %d] say %s\n",new_sock,buf);
write(new_sock,buf,strlen(buf));
}
exit(0);
}
//父进程能够快速再次调用 accept
close(new_sock);//子进程保存了一份父进程的文件描述表
//回收子进程 采用忽略信号的方式
}
int main(int argc,char* argv[]){
if(argc!= 3){
printf ("Usage ./server [ip] [port]\n");
return 1;
}
//忽略子进程信号 子进程就会被系统自动回收
signal(SIGCHLD,SIG_IGN);
int listen_sock = ServerInit(argv[1],atoi(argv[2]));
if(listen_sock < 0){
printf ("ServerInit failed!!! \n");
return 1;
}
printf("ServerInit ok!!! \n");
while(1){
sockaddr_in peer;
socklen_t len = sizeof(peer);
int new_sock = accept(listen_sock,(sockaddr*)&peer,&len);
if(new_sock <0){
perror("accpet");
continue;
}
printf("[client %d] connect!\n",new_sock);
ProcessConnect(new_sock);
}
return 0;
}
/****************** makefile ********************/
.PHONY:all
all:server client server_fork
server:server.c
gcc $^ -o $@
client:client.c
gcc $^ -o $@
server_fork:server_fork.c
gcc $^ -o $@
.PHONY:clean
clean:
rm -f server client server_fork
OSI七层模型:
https://blog.csdn.net/Romantic_C/article/details/81665591
网络套接字:
https://blog.csdn.net/Romantic_C/article/details/81704425
UDP服务器:
https://blog.csdn.net/Romantic_C/article/details/81705468
TCP服务器:
https://blog.csdn.net/Romantic_C/article/details/81707907
应用层:
https://blog.csdn.net/Romantic_C/article/details/81714161
传输层:
https://blog.csdn.net/Romantic_C/article/details/81747317
网络层:
https://blog.csdn.net/Romantic_C/article/details/81751255
数据链路层:
https://blog.csdn.net/Romantic_C/article/details/81777844