基本的思路:用主线程负责client的连接, 然后当有客户端来连接的时候,创建子进程。在子进程里面实现数据的接收。

1.myhead.h

先把一些要用的API的头文件都写进来。

#ifndef _MYHEAD_H_
#define _MYHEAD_H_#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>#define MYPORT 6667           //1024以下的是保留的端口号,用大于1024的;
//#define MYADDR "192.168.1.102"         //把这行注释掉,可以在调用客户端程序时,输入服务器运行的IP来连接服务器 ./client 192.168.1.233#endif

2.server.c

#include "myhead.h"void *read_msg(void *argc);int main()
{int ret = 0;int socketfd = 0;                                //局部变量保存在栈空间,而栈空间是脏的==》里面还是保存的是上一次这个区域里面保存的值;int clientfd = 0;pid_t pid = 0;pthread_t th = 0;struct sockaddr_in sock_server = {0};              //变量类型保存在netinet/in.h里面的;struct sockaddr_in sock_client = {0};          //保存连接的客户端那边的信息;socklen_t len = sizeof(struct sockaddr);//第一步:创建套接字;socketfd = socket(AF_INET,SOCK_STREAM,0);if(socketfd == -1)      //入口检查{perror("socket");    //打印错误信息return -1;}printf("socket success...\n");                 //确保前面的代码是运行正确的;//第二步:给套接字绑定必要的信息;sock_server.sin_family = AF_INET;               //给服务程序绑定地址族;sock_server.sin_port = htons(MYPORT);          //给服务器程序设定个端口号;
//  sock_server.sin_addr.s_addr = inet_addr(MYADDR);//给服务程序绑定IP地址;sock_server.sin_addr.s_addr = htonl(INADDR_ANY);//绑定任意ip地址;这样就能够实现像之前说的./client 192.168.1.233这样使用ret = bind(socketfd,(struct sockaddr *)&sock_server,sizeof(struct sockaddr));if(ret == -1){perror("bind");return -1;}printf("bind success..\n");//第三步:listen监听!ret = listen(socketfd,10);if(ret == -1){perror("listen");return -1;}printf("listen success...\n");//这里的第四步accept放到下面的while(1)里面,有许多client要连接到服务器中来
//  clientfd = accept(socketfd,(struct sockaddr *)&sock_client,&len);
//  if(clientfd == -1)
//  {
//      perror("accept");
//      return -1;
//  }
//  printf("accept success...clinet fd = %d\n",clientfd);while(1){clientfd = accept(socketfd,(struct sockaddr *)&sock_client,&len);if(clientfd == -1){perror("accept");return -1;}printf("accept success... clientfd = %d\n",clientfd);  //客户端连接进来,ret = pthread_create(&th,NULL,read_msg,&clientfd);        //执行read_msg这个函数。传递clientfd,要知道从哪一个客户端来读取数据;if(ret != 0){perror("pthread_create");return -1;}}close(socketfd);return 0;
}void *read_msg(void *argc)
{//argc首先是void类型的指针,经过(int *)argc强制转化为int *的指针,接下来要从argc所指向的地址里面取值;//===>*((int *)argc);===>经过以上的操作就将pthread_create()里面传递的参数,赋值给fd;int fd = *((int *)argc);printf("fd = %d\n",fd);      //验证fd是否等于main函数里面的cleintfd;    4char recvbuff[20] = {0};   //用来保存接收的信息int recvcnt = 0;              //用来存recv函数的返回值while(1){bzero(recvbuff,sizeof(recvbuff));     //先清空recvbuff里面的内容。recvcnt = read(fd,recvbuff,sizeof(recvbuff));    //从recvbuff中读取,sizeof(recvbuff)大小的内容到为文件描述符fd的文件中if(recvcnt == -1){perror("recv");return NULL;}else if(recvcnt == 0)           {printf("The Client is closed!\n");break;}else{printf("Recv from Client %d bytes,data:%s\n",recvcnt,recvbuff);  //打印接收到的信息}if(strcmp(recvbuff,"end") == 0){break;}}close(fd);return NULL;
}

3.client.c

#include "myhead.h"//int main()
int main(int argc,char **argv)
{//参数入口检查;if(argc != 2)              //usage: ./client 192.168.1.233{perror("argc");return -1;}int socketfd = 0;int ret = 0;struct sockaddr_in sock_server = {0};socketfd = socket(AF_INET,SOCK_STREAM,0);        //第一步还是创建套接字if(-1 == socketfd){perror("socket");return -1;}printf("socket success...\n");//用sock_server提醒你们这边连接的是服务器端的IP地址和端口号;sock_server.sin_family = AF_INET;sock_server.sin_port = htons(MYPORT);
//  sock_server.sin_addr.s_addr = inet_addr(MYADDR);sock_server.sin_addr.s_addr = inet_addr(argv[1]);ret = connect(socketfd,(struct sockaddr *)&sock_server,sizeof(struct sockaddr));        //连接服务器if(ret == -1){perror("connect");return -1;}char sendbuff[20] = {0};int sendcnt = 0;while(1){//第一步:提示客户输入要发送的数据;printf("Please input a string:\n");scanf("%s",sendbuff);//第二步:调用send向套接字发送数据;
//      sendcnt = send(socketfd,sendbuff,strlen(sendbuff),0);sendcnt = write(socketfd,sendbuff,strlen(sendbuff));if(sendcnt == -1){perror("send");return -1;}else{printf("Send to Server %d bytes,data:%s\n",sendcnt,sendbuff);}//第三步:判断发送的数据是否是end,如果是,就结束;if(strcmp(sendbuff,"end") == 0){close(socketfd);break;}}return 0;
}

分别编译服务器和客户端程序: 
gcc server.c -o server 
gcc client.c -o client 
然后,先运行服务器./server,再运行客户端./client,客户端发消息给服务器,服务器回复,实现基本的一收一发的功能。

基于TCP协议用多线程实现并发服务器,实现思路、算法和demo相关推荐

  1. java socket发送定长报文_一个基于TCP协议的Socket通信实例

    原标题:一个基于TCP协议的Socket通信实例 1. 前言 一般接口对接多以http/https或webservice的方式,socket方式的对接比较少并且会有一些难度.正好前段时间完成了一个so ...

  2. python中基于tcp协议的通信(数据传输)

    tcp协议:流式协议(以数据流的形式通信传输).安全协议(收发信息都需收到确认信息才能完成收发,是一种双向通道的通信) tcp协议在OSI七层协议中属于传输层,它上承用户层的数据收发,下启网络层.数据 ...

  3. 异常处理、socke基于TCP协议编程

    一.异常处理 1.错误和异常 1.程序中难免出现错误,而错误分成两种 (1)语法错误(这种错误过不了Python解释器的语法检测,必须在程序执行前改正) #语法错误示范一 if#语法错误示范二 def ...

  4. 基于TCP协议的网络程序(基础学习)

    下图是基于TCP协议的客户端/服务器程序的一般流程: 图 37.2. TCP协议通讯流程 服务器调用socket().bind().listen()完成初始化后,调用accept()阻塞等待,处于监听 ...

  5. 基于TCP协议网上聊天程序(python)带界面

    基于TCP协议网上聊天程序(python)带界面 1 设计目标 基于TCP协议网上聊天程序 实现一简单的聊天程序实现网上聊天,包括服务器和客户端. (1)支持多人聊天: (2)客户端具有图形化用户界面 ...

  6. 网络编程——基于TCP协议的通讯录【课程设计】

    网络编程--基于TCP协议的通讯录[课程设计] 本文目录 网络编程--基于TCP协议的通讯录[课程设计] 一.设计题目和要求 设计目标: 课程设计系统组成及模块功能: 二.设计内容 服务端 客户端 S ...

  7. 用C#实现基于TCP协议的网络通讯

    TCP协议是一个基本的网络协议,基本上所有的网络服务都是基于TCP协议的,如HTTP,FTP等等,所以要了解网络编程就必须了解基于TCP协议的编程.然而TCP协议是一个庞杂的体系,要彻底的弄清楚它的实 ...

  8. 基于 tcp协议完成的上传下载

    ps: 下面两个版本全部是 基于 tcp协议完成的. 简单版(无注释): 服务器(server)代码: from socket import socket sk = socket() sk.bind( ...

  9. 网络编程应用:基于TCP协议【实现对象传输】--练习

    要求: 基于TCP协议实现,客服端向服务器发送一个对象 服务器接受并显示用户信息 ,同时返回给客户端 "数据已收到"建一个Student类,属性:name age Student类 ...

最新文章

  1. 概率潜在语义分析(Probabilistic Latent Semantic Analysis,PLSA)
  2. Android混淆打包
  3. load、loads、dump、dumps的区别
  4. JAVA线程间协作:Condition
  5. Linux——好用的一些命令(一)(保持更新)
  6. zabbix监控windows下的mysql
  7. 高级php进修,PHP进修笔记一:PHP的数据类型与常量应用
  8. 云服务器安全组配置(阿里云,ucloud云,华为云)
  9. java svn插件_eclipse 安装SVN插件 subversive
  10. 简便word批量打印 - Office批量打印精灵(支持正版)
  11. PHP利用JWT实现token和refresh_token
  12. 二、用于数据分析的Tableau技巧
  13. cursor android,Android Cursor用法
  14. 谈谈c语言程序如何变成可执行文件,C语言从代码变成可执行程序的步骤
  15. 手游联运系统隐藏福利大揭秘
  16. android pie_Android Pie中的新安全功能,以及为什么对它们感到兴奋
  17. 三维扫描仪的数据化时代
  18. vmware exis如何设置双网卡
  19. Hdu 5804 Price List【水题】
  20. TIME_WAIT详解

热门文章

  1. 苹果电脑强制结束任务,快捷键
  2. 超级详细备注的代码:Python帮助您高效通过英语六级考试
  3. iphone型号表_iphone网络制格式怎么看,如何看两网三网、美版、欧版和国行信号到底有么有区别...
  4. 如何防止网页被Demo
  5. 马斯克提出以430亿收购推特 推特考虑用毒丸来阻止其增持股份
  6. 5G iPhone SE起售价399美元 今年有望出货3000万部
  7. 无惧上代信号差诟病?谷歌Pixel 7系列继续搭载三星基带芯片
  8. 工信部拟规定基本功能软件外的预置App均可卸载
  9. 瑞士信贷上调苹果目标价至168美元
  10. 由于两家重要零件厂商的疫情,iPhone 13备货可能受影响