TCP-server编程
来源:互联网 发布:mac自带画图工具 编辑:程序博客网 时间:2024/06/09 15:48
一、基本解释
在之前的博客中我已经简单的介绍过TCP建立连接时的三次握手,以及在断开连接时的四次挥手,在此我就不再多说了,此次介绍基于TCP的套接字编程。在此类编程中会用到一些结构体以及函数,下来我简单地介绍下这些:
1.struct sockaddr_in
其结构如下
sockaddr_in(在netinet/in.h中定义):
struct sockaddr_in
{
short sin_family;/*Address family一般来说AF_INET(地址族)PF_INET(协议族)*/
unsigned short sin_port;/*Port number(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字)*/
struct in_addr sin_addr;/*IP address in network byte order(Internet address)*/
unsigned char sin_zero[8];/*Same size as struct sockaddr没有实际意义,只是为了 跟SOCKADDR结构在内存中对齐*/
};
2.bind函数
int bind(int sockfd, struct sockaddr* addr,socklen_t addrlen)
- 参数sockfd
- 指定地址与哪个套接字绑定,这是一个由之前的socket函数调用返回的套接字。调用bind的函数之后,该套接字与一个相应的地址关联,发送到这个地址的数据可以通过这个套接字来读取与使用。
- 参数addr
- 正如大多数socket接口一样,内核不关心地址结构,当它复制或传递地址给驱动的时候,它依据这个值来确定需要复制多少数据。这已经成为socket接口中最常见的参数之一了。
- 参数addrlen
- 是参数addr的大小
3.listen函数
int listen(int sock, int backlog);
sock 为需要进入监听状态的套接字,backlog 为请求队列的最大长度。
所谓被动监听,是指当没有客户端请求时,套接字处于“睡眠”状态,只有当接收到客户端请求时,套接字才会被“唤醒”来响应请求。
4.accept函数
int accept(int sock, struct sockaddr *addr,socklen_t *addrlen);
sock 为服务器端套接字,addr 为 sockaddr_in 结构体变量,addrlen 为参数 addr 的长度,可由 sizeof() 求得。
accept() 返回一个新的套接字来和客户端通信,addr 保存了客户端的IP地址和端口号,而 sock 是服务器端的套接字,大家注意区分。后面和客户端通信时,要使用这个新生成的套接字,而不是原来服务器端的套接字。
二、具体编程实现
1.TCP-server
这是一个普通的TCP服务器,可以允许一个客户端进行连接
#include <stdio.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <memory.h>#define MAXN_STR 40void usage(const char* proc){ printf("[%s],[localip],[localport]\n",proc);}int startup(char* ip,int port){ int sock=socket(AF_INET,SOCK_STREAM,0); if(sock<0) { perror("socket\n"); return 0; } struct sockaddr_in local; local.sin_family=AF_INET; local.sin_port=htons(port); local.sin_addr.s_addr=inet_addr(ip); int opt=1; setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0) { perror("bind\n"); return 0; } if(listen(sock,5)<0) { perror("listen"); return 0; } return sock;}int main(int argc,char* argv[]){ if(argc!=3) { usage(argv[0]); return 0; } int listen_sock=startup(argv[1],atoi(argv[2])); char buf[10240]; struct sockaddr_in client; socklen_t len=sizeof(client); while(1) { int new_sock=accept(listen_sock,(struct sockaddr*)&client,&len); if(new_sock<0) { perror("accept"); continue; } close(listen_sock); printf("connect... ip is %s,port is %d\n ",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); while(1) { ssize_t s=read(new_sock,buf,sizeof(buf)-1); if(s>0) { buf[s]='\0'; printf("client say:%s\n",buf); write(new_sock,buf,strlen(buf)); } else if(s==0) { printf("client quit\n"); break; } else { break; } } return 0; } return 0;}
2.TCP-server多进程版本
可以允许多个客户端同时连接
#include <stdio.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <memory.h>#define MAXN_STR 40void usage(const char* proc){ printf("[%s],[localip],[localport]\n",proc);}int startup(char* ip,int port){ int sock=socket(AF_INET,SOCK_STREAM,0); if(sock<0) { perror("socket\n"); return 0; } struct sockaddr_in local; local.sin_family=AF_INET; local.sin_port=htons(port); local.sin_addr.s_addr=inet_addr(ip); int opt=1; setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0) { perror("bind\n"); return 0; } if(listen(sock,5)<0) { perror("listen"); return 0; } return sock;}int main(int argc,char* argv[]){ if(argc!=3) { usage(argv[0]); return 0; } int listen_sock=startup(argv[1],atoi(argv[2])); char buf[1024]; struct sockaddr_in client; socklen_t len=sizeof(client); while(1) { int new_sock=accept(listen_sock,(struct sockaddr*)&client,&len); if(new_sock<0) { perror("accept"); continue; }printf("connect... ip is %s,port is %d \n",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); pid_t id=fork(); if(id>0) { close(new_sock); } else if(id==0) { close(listen_sock); if(fork() > 0) exit(0); while(1) { ssize_t s=read(new_sock,buf,sizeof(buf)-1); if(s>0) { buf[s] = 0; printf("client say:%s\n",buf); write(new_sock,buf,strlen(buf)); } else if(s == 0) { printf("client quit\n"); break; } else { break; } } return 0; } else { perror("fork"); close(listen_sock); return 0; } } return 0;}
3.TCP-server多线程版本
#include <stdio.h>#include <sys/types.h>#include <arpa/inet.h>#include <sys/socket.h>#include <stdlib.h>#include <netinet/in.h>#include <unistd.h>#include <pthread.h>#include <string.h>void usage(char* proc){ printf("%s: [localip], [localport]\n", proc);}int startup(char* ip, int port){ int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock < 0) { perror("socket\n"); return 0; } struct sockaddr_in local; local.sin_family = AF_INET; local.sin_port = htons(port); local.sin_addr.s_addr = inet_addr(ip); int opt = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0) { perror("bind\n"); return 0; } if(listen(sock, 5) < 0) { perror("listen\n"); return 0; } return sock;}void *handlerRequest(void* arg){ int new_fd = (int)arg; while(1) { char buf[1024]; ssize_t s = read(new_fd, buf, sizeof(buf)-1); if(s > 0) { buf[s] = 0; printf("Client: %s\n", buf); write(new_fd, buf, strlen(buf)); } else { printf("Read done..., break\n"); break; } }}int main(int argc, char* argv[]){ if(argc != 3) { usage(argv[0]); } int listen_sock = startup(argv[1], atoi(argv[2])); struct sockaddr_in client; socklen_t len = sizeof(client); while(1) { int new_sock = accept(listen_sock, (struct sockaddr*)&client, &len); if(new_sock < 0) { perror("accept"); continue; } printf("Get a new connect, %s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); pthread_t id; pthread_create(&id, NULL, handlerRequest, (void *)new_sock); pthread_detach(id); } return 0;}
4.TCP-client客户端部分
#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <unistd.h>static void usage(const char* proc){ printf("%s:[service_ip],[service_port]\n",proc);}int main(int argc, char* argv[]){ if(argc != 3) { usage(argv[0]); return 1; } int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock < 0) { perror("sock"); return 2; } struct sockaddr_in remote; remote.sin_family = AF_INET; remote.sin_port = htons(atoi(argv[2])); remote.sin_addr.s_addr = inet_addr(argv[1]); if(connect(sock, (struct sockaddr*)&remote, sizeof(remote)) < 0) { perror("connect"); return 2; } while(1) { char buf[1024]; printf("Please enter:\n"); fflush(stdout); ssize_t s = read(0, buf, sizeof(buf)-1); if(s > 0) { buf[s-1] = 0; write(sock, buf, sizeof(buf) - 1); ssize_t _s=read(sock, buf, sizeof(buf) - 1); if(_s > 0) { buf[_s] = 0; printf("server echo# %s\n", buf); } } } return 0;}
- TCP-server编程
- QT Socket编程--TCP Server
- Python网络编程---TCP Server
- TCP/IP编程·Server
- 简单网络编程--TCP SERVER 端
- TCP server Socket编程 VC++6.0
- TCP server
- TCP Server
- tcp-server
- TCP--server
- Linux下Socket编程之TCP Server端
- socket 编程入门教程(一)TCP server 端:1、建模
- socket 编程入门教程(一)TCP server 端:1、建模
- 嵌入式linux的网络编程(2)--TCP Server程序设计
- 【winsock2】windows网络编程 之 TCP/IP Server
- linux下面TCP套接口编程 client/server实例
- linux下的tcp的server和client编程
- 嵌入式linux的网络编程(2)--TCP Server程序设计
- kinect-点云数据、深度数据&ros中相关主题
- Jmeter测试报告优化
- mybatis入门基础(八)-----查询缓存
- 3DSystems.Geomagic.Sculpt.2016.2.62 Ansys.OptiSLang.5.2.0.38449 Ansys.Products.18.0 win+linux Aspen.
- Hive 快速入门
- TCP-server编程
- 【机器人与小车互联项目】项目方案
- 数据存储系统的 80/20 法则
- spring-boot-devtools 不同ClassLoader引起的问题
- net.sf.json.JSONObject 和org.json.JSONObject 的差别
- volatile与synchronized的区别
- IOS图片转换格式
- TCP/IP服务器
- 利用正则表达式提取docx转为txt的文件。