TCP套接字(server/client实现)
来源:互联网 发布:面向对象编程什么意思 编辑:程序博客网 时间:2024/05/24 01:11
套接字
- 概念:源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字。其用于标识客户端请求的服务器和服务。
- 分类:
- 流套接字(SOCK_STREAM)
- 数据报套接字(SOCK_DGRAM)
- 原始套接字(SOCK_RAW)
TCP套接字(流套接字)
- TCP套接字工作流程:
- 首先,服务器端启动进程,调用Socket创建一个基于TCP协议的流套接字描述符。
- 其次,服务进程调用bind命名套接字,将套接字描述符绑定到本地地址和本地端口上。
- 再次,服务器端调用listen,开始侦听客户端的Socket连接请求。
- 接下来,客户端创建套接字描述符,并且调用connect向服务器端提交连接请求。服务器端接收到客户端连接请求后,调用accept,接受并创建一个新的套接字描述符与客户端建立连接,然后原套接字描述符继续侦听客户端的连接请求。
- 客户端与服务器端新套接字进行数据传输,调用write或send向对方发送数据,调用read或recv接收数据。
- 代码
server.c#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<unistd.h>#include<stdlib.h>#include<netinet/in.h>#include<arpa/inet.h>#include<string.h>#include<pthread.h>static void usage(const char* proc){ printf("usage: %s [local_ip] [local_port]\n",proc);}int start_up(const char* _ip,int _port){ int sk = socket(AF_INET,SOCK_STREAM,0); if(sk < 0) { perror("socket"); exit(2); } struct sockaddr_in local; local.sin_family = AF_INET; local.sin_port = htons(_port); local.sin_addr.s_addr = inet_addr(_ip); if(bind(sk,(struct sockaddr *)&local,sizeof(local)) < 0) { perror("bind"); exit(3); } if(listen(sk,10) < 0) { perror("listen"); exit(4); } return sk;}void* handlerquest(void*arg){// close(listen_sk); int new_sk = (int)arg; while(1) { char buf[1024]; ssize_t s = read(new_sk,buf,sizeof(buf)-1); if(s > 0) { buf[s] = 0; printf("client:%s\n",buf); write(new_sk,buf,strlen(buf)); } else { close(new_sk); printf("client quit ...\n"); break; } }}int main(int argc,char* argv[]){ if(argc != 3) { usage(argv[0]); return 1; } int listen_sk = start_up(argv[1],atoi(argv[2])); while(1) { struct sockaddr_in client; socklen_t len = sizeof(client); int new_sk = accept(listen_sk,(struct sockaddr*)(&client),&len); if(new_sk < 0) { perror("accept"); continue; } printf("Get a new client %s : %d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));//多线程 pthread_t id; pthread_create(&id,NULL,handlerquest,(void*)new_sk); pthread_detach(id);//多进程 // pid_t id = fork(); // if(id < 0) // { // close(new_sk); // } // else if(id == 0) // { // close(listen_sk); // if(fork()<0) // { // exit(0); // } // while(1) // { // char buf[1024]; // ssize_t s = read(new_sk,buf,sizeof(buf)-1); // if(s > 0) // { // buf[s] = 0; // printf("client:%s\n",buf); // write(new_sk,buf,strlen(buf)); // } // else // { // close(new_sk); // printf("client quit ...\n"); // break; // } // } // close(new_sk); // } // else // { // close(new_sk); // }//普通版 // while(1) // { // char buf[1024]; // ssize_t s = read(new_sk,buf,sizeof(buf)-1); // if(s > 0) // { // buf[s] = 0; // printf("client:%s\n",buf); // write(new_sk,buf,strlen(buf)); // } // else // { // close(new_sk); // printf("client quit ...\n"); // break; // } // } } return 0;}
client.c#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<string.h>#include<stdlib.h>#include<netinet/in.h>#include<arpa/inet.h>void usage(const char* proc){ printf("usage:%s [local_ip] [local_port]\n");}int main(int argc,char* argv[]){ if(argc != 3) { usage(argv[0]); return 1; } int sk = socket(AF_INET,SOCK_STREAM,0); if(sk <0 ) { perror("socket"); return 1; } struct sockaddr_in server; server.sin_family = AF_INET; server.sin_port = htons(atoi(argv[2])); server.sin_addr.s_addr = inet_addr(argv[1]); if(connect(sk,(struct sockaddr*)&server,sizeof(server))<0) { perror("connect"); exit(1); } char buf[1024]; while(1) { printf("Please Enter#:"); fflush(stdout); ssize_t s = read(0,buf,sizeof(buf)-1); if(s > 0) { buf[s-1] = 0; write(sk,buf,strlen(buf)); s = read(sk,buf,sizeof(buf)-1); if(s > 0) { buf[s] = 0; printf("server echo# %s\n",buf); } } } return 0;}
makefile.PHONY:allall:tcp_server tcp_clienttcp_client:tcp_client.c gcc -o $@ $^ tcp_server:tcp_server.c gcc -o $@ $^ -lpthread.PHONY:cleanclean: rm -f tcp_client tcp_serve
服务器退出,客户端不退出,当再次运行服务器(与之前的端口号相同),就会出现绑定失败。
- 原因:
主动关闭的一方在发送最后一个ack 后就会进入TIME_WAIT状态 停留2MSL(max segment lifetime)时间。这个TCP/IP必不可少的,也就是“解决”不了的。也就是TCP/IP设计者本来是这么设计的。主要有两个原因- 防止上一次连接中的包,迷路后重新出现,影响新连接(经过2MSL,上一次连接中所有的重复包都会消失)
- 可靠的关闭TCP连接
在主动关闭方发送的最后一个ack(fin) ,有可能丢失,这时被动方会重新发 fin, 如果这时主动方处于CLOSED 状态 ,就会响应rst 而不是ack。所以主动方要处于TIME_WAIT 状态,而不能是CLOSED 。
TIME_WAIT 并不会占用很大资源的,除非受到攻击。还有,如果一方send 或recv 超时,就会直接进入CLOSED 状态
[http://blog.csdn.net/acs713/article/details/28427181]
阅读全文
0 0
- TCP套接字(server/client实现)
- 网络套接字socket(tcp、server、client)
- TCP/IP(7)-TCP Server与TCP Client(linux套接字)
- TCP/IP(8)-UDP Server与UDP Client(linux套接字)
- TCP-server/client实现字符大写转换
- 套接字(socket)编程简单实现server-client聊天程序
- 套接字实现Tcp服务器
- 套接字实现TCP服务器
- java Tcp Client server
- linux tcp server client
- TCP:Server-Client程序
- ECHO TCP Server Client
- gevent tcp server&client
- TCP Server/Client, Select
- TCP Socket Server Client
- tcp client and server
- golang tcp server client
- 使用TCP套接字实现文件服务器
- Qt 实现 HMAC_SHA1 哈希算法
- SDL2.0 使用互斥量
- AfxGetApp用法
- apt-get install 下载太慢怎么办,用apt-fast!
- springMVC-参数绑定(服务器接收页面传来的参数)返回值转换为JSON
- TCP套接字(server/client实现)
- ZStack(CC2530) 断电存储(NV)方法
- 汇编-字符串小写转大写
- Android 序列化学习总结
- HBase笔记-4.HBase的mapredece
- 探索MFC全局函数-AfxGetApp()
- win10卸载ubuntu
- HALCON安装与配置(VS2013+HALCON13)
- 国际化测试-ICU