socket套接字编写多线程多进程的server和client
来源:互联网 发布:学统计跟大数据 编辑:程序博客网 时间:2024/05/17 00:11
关于套接字编程
套接字编程
IP地址+端口号就成为套接字
在TCP协议中。建立两个连接的进程个字有一个socket来标识,那么这两个socket组成desocketpair就表示一个唯一链接
socket用来描述网络连接一对一关系
socket地址的数据类型及相关函数
第一个是通用接口
第二个表示IPV4的地址使用socketaddr_in
第三个表示预间套接字
这样我们只需要知道某种socket结构体的首地址,就可以根据地质的具体类型字段确定结构体中的内容
服务器需要进行的操作
1>、服务器首先获得sockect调用socket函数
在这里我们用的是IPV4因此类型选择AF_INET。
由于是16位地址类型的AF_INET的所以我们采用sockaddr_in 类型的
客户端和服务端是一样的
sa_family:表示地址所属的类型 在这道理我们是AF_INET
_be16代表16位端口号
为什么是16位,因为在这里我们是从上往下进行交付
TCP的报头是16位端口号
server.sin_port=htons(atoi(port));
htons的功能:将一个无符号短整型数值转换为网络字节序,即大端模式(big-endian)
2>、接下来就应该绑定端口 调用bind函数绑定IP和端口号
3>、接下来服务器需要不断去监听有没有客户端发来请求调用listen函数
4>、接下来我们需要调用accept函数
accept()系统调用主要用在基于连接的套接字类型,比如SOCK_STREAM和SOCK_SEQPACKET。它提取出所监听套接字的等待连接队列中第一个连接请求,创建一个新的套接字,并返回指向该套接字的文件描述符。新建立的套接字不在监听状态,原来所监听的套接字也不受该系统调用的影响。
5>、之后就可以进行一系列的读写操作了
2、客户端进行的操作就比较简单,他只需要和服务器进行连接
version1版本的server和client
server.c#include<stdio.h>#include <sys/types.h> #include <sys/socket.h>#include<arpa/inet.h>#include<netinet/in.h>#include<string.h>#include<unistd.h>#include<stdlib.h>int startup(char*ip,int port){ int sock=socket(AF_INET,SOCK_STREAM,0); if(sock<0) { perror("socket"); exit(2); } struct sockaddr_in server; server.sin_family=AF_INET; server.sin_port=htons(atoi(port)); server.sin_addr.s_addr=inet_addr(ip); if(bind(sock,(struct sockaddr*)&server,sizeof(struct sockaddr_in))<0) { perror("bind"); exit(3); } if(listen(sock,10)<0) { perror("listen"); exit(4); } return sock;}void *usage(const char*proc){ printf("%s [local_ip] [local_port]\n",proc); exit(5);}int main(int argv,char*argc[]){ if(argv!=3) { usage(argc[0]); exit(6); } int listen_sock=startup(argc[1],argc[2]); printf("fd:%d\n",listen_sock); while(1) { struct sockaddr_in client; socklen_t len=sizeof(client); int newsock=accept(listen_sock,(struct sockaddr*)&client,&len); if(newsock<0) { perror("accept"); continue; } printf("get a client:[%s:%d]\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); char buf[1024]; while(1) { ssize_t ret=read(newsock,buf,sizeof(buf)-1); if(ret>0) { buf[ret]=0; printf("client say:%s\n",buf); write(newsock,buf,sizeof(buf)-1); } else if(ret==0) { printf("client quit!\n"); break; } else { perror("read"); exit(7); } } close(newsock); } close(listen_sock); return 0;}
client.c#include<stdio.h>#include <sys/types.h> #include <sys/socket.h>#include<arpa/inet.h>#include<netinet/in.h>#include<string.h>#include<unistd.h>#include<stdlib.h>void Usage(char*proc){ printf("%s [server_ip] [server_port]\n",proc); return 1;}int main(int argv,char*argc[]){ if(argv!=3) { Usage(argc[0]); return 2; } int sock=socket(AF_INET,SOCK_STREAM,0); struct sockaddr_in server_sock; server_sock.sin_family=AF_INET; server_sock.sin_port=htons(atoi(argc[2])); server_sock.sin_addr.s_addr=inet_addr(argc[1]); if(connect(sock,(struct sockaddr*)(&server_sock),sizeof(server_sock))<0) { perror("connect"); return 3; } while(1) { printf("please Enter:\n"); fflush(stdout); char buf[1024]; ssize_t ret=read(0,buf,sizeof(buf)-1); if(ret>0) { buf[ret-1]=0; write(sock,buf,sizeof(buf)-1); read(sock,buf,sizeof(buf)-1); printf("server say:%s\n",buf); }} close(sock); return 3;}
多进程版本的:
**server.c**#include<stdio.h>#include <sys/types.h> #include <sys/socket.h>#include<arpa/inet.h>#include<netinet/in.h>#include<string.h>#include<unistd.h>#include<stdlib.h>int startup(char*ip, int port){ int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock<0) { perror("socket"); exit(2); } struct sockaddr_in server; server.sin_family = AF_INET; server.sin_port = htons(atoi(port)); server.sin_addr.s_addr = inet_addr(ip); if (bind(sock, (struct sockaddr*)&server, sizeof(struct sockaddr_in))<0) { perror("bind"); exit(3); } if (listen(sock, 10)<0) { perror("listen"); exit(4); } return sock;}void *usage(const char*proc){ printf("%s [local_ip] [local_port]\n", proc); exit(5);}int main(int argv, char*argc[]){ if(argv!=3) { Usage(argc[0]); } int listen_sock = startup(argc[1], argc[2]); printf("fd:%d\n", listen_sock); while (1) { struct sockaddr_in client; socklen_t len = sizeof(client); int newsock = accept(listen_sock, (struct sockaddr*)&client, &len); if (newsock<0) { perror("accept"); continue; } printf("get a client:[%s:%d]\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); pid_t id = fork(); if (id == 0) { close(listen_sock); if (fork() == 0) { char buf[1024]; while (1) { ssize_t ret = read(newsock, buf, sizeof(buf)-1); if (ret>0) { buf[ret] = 0; printf("client say:%s\n", buf); write(newsock, buf, sizeof(buf)-1); } else if (ret == 0) { printf("client quit!\n"); close(newsock); exit(7); } else { perror("read"); exit(8); } } } else { exit(9); } } else if (id>0) { close(newsock); while((waitpid(-1,NULL,WNOHANG)>0)); continue; } else { perror("fork"); exit(9); } } close(listen_sock); return 0;}
多线程版本的:
#include<stdio.h>#include <sys/types.h> #include <sys/socket.h>#include<arpa/inet.h>#include<netinet/in.h>#include<string.h>#include<unistd.h>#include<stdlib.h>#include <pthread.h>int startup(char*ip, int port){ int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock<0) { perror("socket"); exit(2); } struct sockaddr_in server; server.sin_family = AF_INET; server.sin_port = htons(atoi(port)); server.sin_addr.s_addr = inet_addr(ip); if (bind(sock, (struct sockaddr*)&server, sizeof(struct sockaddr_in))<0) { perror("bind"); exit(3); } if (listen(sock, 10)<0) { perror("listen"); exit(4); } return sock;}void *Usage(const char*proc){ printf("%s [local_ip] [local_port]\n", proc); exit(5);}void* thread_handler(void*arg){ int newsock=*((int*)arg); char buf[1024]; while (1) { ssize_t ret = read(newsock, buf, sizeof(buf)-1); if (ret>0) { buf[ret] = 0; printf("client say:%s\n", buf); write(newsock, buf, sizeof(buf)-1); } else if (ret == 0) { printf("client quit!\n"); close(newsock); exit(7); } else { perror("read"); exit(8); } }}int main(int argv, char*argc[]){ if(argv!=3) { Usage(argc[0]); } int listen_sock = startup(argc[1], argc[2]); printf("fd:%d\n", listen_sock); while (1) { struct sockaddr_in client; socklen_t len = sizeof(client); int newsock = accept(listen_sock, (struct sockaddr*)&client, &len); if (newsock<0) { perror("accept"); continue; } printf("get a client:[%s:%d]\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); pthread_t tid; int ret=pthread_create(&tid,NULL,thread_handler,&newsock); if(ret<0) { perror("pthread_create"); exit(9); } pthread_detach(tid);} close(listen_sock); return 0; }
为什么会出现server bind失败
看下图:
由于我们的客户端还没有退出,服务器就先断开连接了造成了这种情况,为什么会出现这种现象呢?
通信双方建立TCP连接后,主动关闭连接的一方就会进入TIME_WAIT状态
TCP是全双工的通信,它是提供可靠传输的,它有着三次握手和四次挥手,在四次挥手的过程中,主动断开连接的一方会进入TIME_WAIT状态。如果服务器端先断开连接那么就会进入TIME_WAIT状态。为什么需要TIME_WAIT?TIME_WAIT是TCP协议用以保证被重新分配的socket不会受到之前残留的延迟重发报文影响的机制,是必要的逻辑保证。
- socket套接字编写多线程多进程的server和client
- client.c和server.c 网络套接字socket编程热身程序
- 网络套接字socket(tcp、server、client)
- linux下 socket tcp Server c语言编写(分别实现单进程,多进程,多线程)
- Linux C语言编程-Linux网络通信--Linux上使用套接字(socket)来处理信息---编写一个单进程非阻塞多客户的套接字客户端
- 基于TCP的server和client编写。
- Java Socket编程 多线程server和client通信demo
- 套接字描述符在多进程和多线程下的共享
- 1.socket编程:socket编程,网络字节序,函数介绍,IP地址转换函数,sockaddr数据结构,网络套接字函数,socket相关函数,TCP server和client
- 1.socket编程:socket编程,网络字节序,函数介绍,IP地址转换函数,sockaddr数据结构,网络套接字函数,socket相关函数,TCP server和client
- Python实现套接字(Socket)的客户端(Client)
- 如何编写Socket套接字
- 如何编写socket套接字
- 如何编写Socket套接字?
- 如何编写Socket套接字
- 如何编写Socket套接字
- 使用Socket编写Client-Server通信总结
- 套接字(socket)编程简单实现server-client聊天程序
- 老旧的金融机构,是时候赶赶云计算的时髦了
- gdfgfdgdf
- kryo序列化反序列化实例
- linux 从一台机器复制文件到另一台linux机器上去
- 完美的代价
- socket套接字编写多线程多进程的server和client
- App端实现免填邀请码建立上下级关系(openinstall)
- android实现透明状态栏
- 再也不敢相信野鸡博文了-MySQL配置
- 思维导图--数据结构导论(2)
- 计算后缀表达式的值:JAVA-Stack实现
- 1002 A+B for Polynomials (25)
- Maze (广搜)
- 简单框架使用