socket多人聊天程序C语言版(二)

socket多人聊天程序C语言版(一)地址: http://www.jb51.net/article/94938.htm

1V1实现了,1V多也就容易了。不过相对于1V1的程序,我经过大改,采用链表来动态管理。这样效率真的提升不少,至少CPU使用率稳稳的在20以下,不会飙到100了。用C语言写这个还是挺费时间的,因为什么功能函数都要自己写,不像C++有STL库可以用,MFC写就更简单了,接下来我还会更新MFC版本的多人聊天程序。好了,废话少说,进入主题。

这个程序要解决的问题如下:

1.CPU使用率飙升问题 –>用链表动态管理

2.用户自定义聊天,就是想跟谁聊跟谁聊 –> _Client结构体中新增一个ChatName字段,用来表示要和谁聊天,这个字段很重要,因为server转发消息的时候就是按照这个字段来转发的。

3.中途换人聊天,就是聊着聊着,想和别人聊,而且自己还一样能接收到其它人发的消息 –> 这个就要小改客户端的代码了,可以在发送聊天消息之前插入一段代码,用来切换聊天用户。具体做法就是,用getch()函数读取ESC键,如果用户按了这个键,则表示想切换用户,然后会输出一行提示,请输入chat name,就是想要和谁聊天的名字,发送这个名字过去之前要加一个标识符,表示这个消息是切换聊天用户消息。然后server接收到这个消息后会判断第一个字符是不是标识符,第二个字符不能是标识符,则根据这个name来查找当前在线的用户,然后修改想切换聊天用户的ChatName为name这个用户。(可能有点绕,不懂的看代码就清晰易懂了~)

4.下线后提醒对方 –> 还是老套路,只要send对方不通就当对方下线了。

编写环境:WIN10,VS2015

效果图:

为了方便就不用虚拟机演示了,但是在虚拟机是肯定可以的,应该说只要是局域网,能互相ping通就可以使用这个程序。

Server code:

链表头文件:

#ifndef _CLIENT_LINK_LIST_H_
#define _CLIENT_LINK_LIST_H_

#include <WinSock2.h>

#include <stdio.h>

//客户端信息结构体
typedef struct _Client
{
 SOCKET sClient;   //客户端套接字
 char buf[128];   //数据缓冲区
 char userName[16];  //客户端用户名
 char IP[20];   //客户端IP
 unsigned short Port; //客户端端口
 UINT_PTR flag;   //标记客户端,用来区分不同的客户端
 char ChatName[16];  //指定要和哪个客户端聊天
 _Client* next;   //指向下一个结点
}Client, *pClient;

/* * function 初始化链表 * return 无返回值 */
void Init();

/* * function 获取头节点 * return 返回头节点 */
pClient GetHeadNode();

/* * function 添加一个客户端 * param client表示一个客户端对象 * return 无返回值 */
void AddClient(pClient client);

/* * function 删除一个客户端 * param flag标识一个客户端对象 * return 返回true表示删除成功,false表示失败 */
bool RemoveClient(UINT_PTR flag);

/* * function 根据name查找指定客户端 * param name是指定客户端的用户名 * return 返回一个client表示查找成功,返回INVALID_SOCKET表示无此用户 */
SOCKET FindClient(char* name);

/* * function 根据SOCKET查找指定客户端 * param client是指定客户端的套接字 * return 返回一个pClient表示查找成功,返回NULL表示无此用户 */
pClient FindClient(SOCKET client);

/* * function 计算客户端连接数 * param client表示一个客户端对象 * return 返回连接数 */
int CountCon();

/* * function 清空链表 * return 无返回值 */
void ClearClient();

/* * function 检查连接状态并关闭一个连接 * return 返回值 */
void CheckConnection();

/* * function 指定发送给哪个客户端 * param FromName,发信人 * param ToName, 收信人 * param data, 发送的消息 */
void SendData(char* FromName, char* ToName, char* data);

#endif //_CLIENT_LINK_LIST_H_

链表cpp文件:

#include "ClientLinkList.h"

pClient head = (pClient)malloc(sizeof(_Client)); //创建一个头结点

/* * function 初始化链表 * return 无返回值 */
void Init()
{
 head->next = NULL;
}

/* * function 获取头节点 * return 返回头节点 */
pClient GetHeadNode()
{
 return head;
}

/* * function 添加一个客户端 * param client表示一个客户端对象 * return 无返回值 */
void AddClient(pClient client)
{
 client->next = head->next; //比如:head->1->2,然后添加一个3进来后是
 head->next = client;  //3->1->2,head->3->1->2
}

/* * function 删除一个客户端 * param flag标识一个客户端对象 * return 返回true表示删除成功,false表示失败 */
bool RemoveClient(UINT_PTR flag)
{
 //从头遍历,一个个比较
 pClient pCur = head->next;//pCur指向第一个结点
 pClient pPre = head;  //pPre指向head
 while (pCur)
 {
  // head->1->2->3->4,要删除2,则直接让1->3
  if (pCur->flag == flag)
  {
   pPre->next = pCur->next;
   closesocket(pCur->sClient); //关闭套接字
   free(pCur); //释放该结点
   return true;
  }
  pPre = pCur;
  pCur = pCur->next;
 }
 return false;
}

/* * function 查找指定客户端 * param name是指定客户端的用户名 * return 返回socket表示查找成功,返回INVALID_SOCKET表示无此用户 */
SOCKET FindClient(char* name)
{
 //从头遍历,一个个比较
 pClient pCur = head;
 while (pCur = pCur->next)
 {
  if (strcmp(pCur->userName, name) == 0)
   return pCur->sClient;
 }
 return INVALID_SOCKET;
}

/* * function 根据SOCKET查找指定客户端 * param client是指定客户端的套接字 * return 返回一个pClient表示查找成功,返回NULL表示无此用户 */
pClient FindClient(SOCKET client)
{
 //从头遍历,一个个比较
 pClient pCur = head;
 while (pCur = pCur->next)
 {
  if (pCur->sClient == client)
   return pCur;
 }
 return NULL;
}

/* * function 计算客户端连接数 * param client表示一个客户端对象 * return 返回连接数 */
int CountCon()
{
 int iCount = 0;
 pClient pCur = head;
 while (pCur = pCur->next)
  iCount++;
 return iCount;
}

/* * function 清空链表 * return 无返回值 */
void ClearClient()
{
 pClient pCur = head->next;
 pClient pPre = head;
 while (pCur)
 {
  //head->1->2->3->4,先删除1,head->2,然后free 1
  pClient p = pCur;
  pPre->next = p->next;
  free(p);
  pCur = pPre->next;
 }
}

/* * function 检查连接状态并关闭一个连接 * return 返回值 */
void CheckConnection()
{
 pClient pclient = GetHeadNode();
 while (pclient = pclient->next)
 {
  if (send(pclient->sClient, "", sizeof(""), 0) == SOCKET_ERROR)
  {
   if (pclient->sClient != 0)
   {
    printf("Disconnect from IP: %s,UserName: %s\n", pclient->IP, pclient->userName);
    char error[128] = { 0 }; //发送下线消息给发消息的人
    sprintf(error, "The %s was downline.\n", pclient->userName);
    send(FindClient(pclient->ChatName), error, sizeof(error), 0);
    closesocket(pclient->sClient); //这里简单的判断:若发送消息失败,则认为连接中断(其原因有多种),关闭该套接字
    RemoveClient(pclient->flag);
    break;
   }
  }
 }
}

/* * function 指定发送给哪个客户端 * param FromName,发信人 * param ToName, 收信人 * param data, 发送的消息 */
void SendData(char* FromName, char* ToName, char* data)
{
 SOCKET client = FindClient(ToName); //查找是否有此用户
 char error[128] = { 0 };
 int ret = 0;
 if (client != INVALID_SOCKET && strlen(data) != 0)
 {
  char buf[128] = { 0 };
  sprintf(buf, "%s: %s", FromName, data); //添加发送消息的用户名
  ret = send(client, buf, sizeof(buf), 0);
 }
 else//发送错误消息给发消息的人
 {
  if(client == INVALID_SOCKET)
   sprintf(error, "The %s was downline.\n", ToName);
  else
   sprintf(error, "Send to %s message not allow empty, Please try again!\n", ToName);
  send(FindClient(FromName), error, sizeof(error), 0);
 }
 if (ret == SOCKET_ERROR)//发送下线消息给发消息的人
 {
  sprintf(error, "The %s was downline.\n", ToName);
  send(FindClient(FromName), error, sizeof(error), 0);
 }

}

server cpp:

/*

#include <WinSock2.h>
#include <process.h>
#include <stdlib.h>
#include "ClientLinkList.h"
#pragma comment(lib,"ws2_32.lib")

SOCKET g_ServerSocket = INVALID_SOCKET;  //服务端套接字
SOCKADDR_IN g_ClientAddr = { 0 };   //客户端地址
int g_iClientAddrLen = sizeof(g_ClientAddr);

typedef struct _Send
{
 char FromName[16];
 char ToName[16];
 char data[128];
}Send,*pSend;

//发送数据线程
unsigned __stdcall ThreadSend(void* param)
{
 pSend psend = (pSend)param; //转换为Send类型
 SendData(psend->FromName, psend->ToName, psend->data); //发送数据
 return 0;
}

//接受数据
unsigned __stdcall ThreadRecv(void* param)
{
 int ret = 0;
 while (1)
 {
  pClient pclient = (pClient)param;
  if (!pclient)
   return 1;
  ret = recv(pclient->sClient, pclient->buf, sizeof(pclient->buf), 0);
  if (ret == SOCKET_ERROR)
   return 1;
  if (pclient->buf[0] == '#' && pclient->buf[1] != '#') //#表示用户要指定另一个用户进行聊天
  {
   SOCKET socket = FindClient(&pclient->buf[1]); //验证一下客户是否存在
   if (socket != INVALID_SOCKET)
   {
    pClient c = (pClient)malloc(sizeof(_Client));
    c = FindClient(socket);      //只要改变ChatName,发送消息的时候就会自动发给指定的用户了
    memset(pclient->ChatName, 0, sizeof(pclient->ChatName));
    memcpy(pclient->ChatName , c->userName,sizeof(pclient->ChatName));
   }
   else
    send(pclient->sClient, "The user have not online or not exits.",64,0);
   continue;
  }

  pSend psend = (pSend)malloc(sizeof(_Send));
  //把发送人的用户名和接收消息的用户和消息赋值给结构体,然后当作参数传进发送消息进程中
  memcpy(psend->FromName, pclient->userName, sizeof(psend->FromName));
  memcpy(psend->ToName, pclient->ChatName, sizeof(psend->ToName));
  memcpy(psend->data, pclient->buf, sizeof(psend->data));
  _beginthreadex(NULL, 0, ThreadSend, psend, 0, NULL);
  Sleep(200);
 }

 return 0;
}

//开启接收消息线程
void StartRecv()
{
 pClient pclient = GetHeadNode();
 while (pclient = pclient->next)
  _beginthreadex(NULL, 0, ThreadRecv, pclient, 0, NULL);
}

//管理连接
unsigned __stdcall ThreadManager(void* param)
{
 while (1)
 {
  CheckConnection(); //检查连接状况
  Sleep(2000);  //2s检查一次
 }

 return 0;
}

//接受请求
unsigned __stdcall ThreadAccept(void* param)
{
 _beginthreadex(NULL, 0, ThreadManager, NULL, 0, NULL);
 Init(); //初始化一定不要再while里面做,否则head会一直为NULL!!!
 while (1)
 {
  //创建一个新的客户端对象
  pClient pclient = (pClient)malloc(sizeof(_Client));

  //如果有客户端申请连接就接受连接
  if ((pclient->sClient = accept(g_ServerSocket, (SOCKADDR*)&g_ClientAddr, &g_iClientAddrLen)) == INVALID_SOCKET)
  {
   printf("accept failed with error code: %d\n", WSAGetLastError());
   closesocket(g_ServerSocket);
   WSACleanup();
   return -1;
  }
  recv(pclient->sClient, pclient->userName, sizeof(pclient->userName), 0); //接收用户名和指定聊天对象的用户名
  recv(pclient->sClient, pclient->ChatName, sizeof(pclient->ChatName), 0);

  memcpy(pclient->IP, inet_ntoa(g_ClientAddr.sin_addr), sizeof(pclient->IP)); //记录客户端IP
  pclient->flag = pclient->sClient; //不同的socke有不同UINT_PTR类型的数字来标识
  pclient->Port = htons(g_ClientAddr.sin_port);
  AddClient(pclient); //把新的客户端加入链表中

  printf("Successfuuly got a connection from IP:%s ,Port: %d,UerName: %s , ChatName: %s\n",
   pclient->IP, pclient->Port, pclient->userName,pclient->ChatName);

  if (CountCon() >= 2)      //当至少两个用户都连接上服务器后才进行消息转发
   StartRecv();

  Sleep(2000);
 }
 return 0;
}

//启动服务器
int StartServer()
{
 //存放套接字信息的结构
 WSADATA wsaData = { 0 };
 SOCKADDR_IN ServerAddr = { 0 };    //服务端地址
 USHORT uPort = 18000;      //服务器监听端口

 //初始化套接字
 if (WSAStartup(MAKEWORD(2, 2), &wsaData))
 {
  printf("WSAStartup failed with error code: %d\n", WSAGetLastError());
  return -1;
 }
 //判断版本
 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
 {
  printf("wVersion was not 2.2\n");
  return -1;
 }
 //创建套接字
 g_ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 if (g_ServerSocket == INVALID_SOCKET)
 {
  printf("socket failed with error code: %d\n", WSAGetLastError());
  return -1;
 }

 //设置服务器地址
 ServerAddr.sin_family = AF_INET;//连接方式
 ServerAddr.sin_port = htons(uPort);//服务器监听端口
 ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//任何客户端都能连接这个服务器

 //绑定服务器
 if (SOCKET_ERROR == bind(g_ServerSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr)))
 {
  printf("bind failed with error code: %d\n", WSAGetLastError());
  closesocket(g_ServerSocket);
  return -1;
 }
 //设置监听客户端连接数
 if (SOCKET_ERROR == listen(g_ServerSocket, 20000))
 {
  printf("listen failed with error code: %d\n", WSAGetLastError());
  closesocket(g_ServerSocket);
  WSACleanup();
  return -1;
 }

 _beginthreadex(NULL, 0, ThreadAccept, NULL, 0, 0);
 for (int k = 0;k < 100;k++) //让主线程休眠,不让它关闭TCP连接.
  Sleep(10000000);

 //关闭套接字
 ClearClient();
 closesocket(g_ServerSocket);
 WSACleanup();
 return 0;
}

int main()
{
 StartServer(); //启动服务器

 return 0;
}

Client code:

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#pragma comment(lib,"ws2_32.lib")
#define RECV_OVER 1
#define RECV_YET 0
char userName[16] = { 0 };
char chatName[16] = { 0 };
int iStatus = RECV_YET;
//接受数据
unsigned __stdcall ThreadRecv(void* param)
{
 char buf[128] = { 0 };
 while (1)
 {
  int ret = recv(*(SOCKET*)param, buf, sizeof(buf), 0);
  if (ret == SOCKET_ERROR)
  {
   Sleep(500);
   continue;
  }
  if (strlen(buf) != 0)
  {
   printf("%s\n", buf);
   iStatus = RECV_OVER;
  }
  else
   Sleep(100); 

 }
 return 0;
}

//发送数据
unsigned __stdcall ThreadSend(void* param)
{
 char buf[128] = { 0 };
 int ret = 0;
 while (1)
 {
  int c = getch();
  if (c == 27) //ESC ASCII是27
  {
   memset(buf, 0, sizeof(buf));
   printf("Please input the chat name:");
   gets_s(buf);
   char b[17] = { 0 };
   sprintf(b, "#%s", buf);
   ret = send(*(SOCKET*)param,b , sizeof(b), 0);
   if (ret == SOCKET_ERROR)
    return 1;
   continue;
  }
  if(c == 72 || c == 0 || c == 68)//为了显示美观,加一个无回显的读取字符函数
   continue;     //getch返回值我是经过实验得出如果是返回这几个值,则getch就会自动跳过,具体我也不懂。
  printf("%s: ", userName);
  gets_s(buf);
  ret = send(*(SOCKET*)param, buf, sizeof(buf), 0);
  if (ret == SOCKET_ERROR)
   return 1;
 }
 return 0;
}

//连接服务器
int ConnectServer()
{
 WSADATA wsaData = { 0 };//存放套接字信息
 SOCKET ClientSocket = INVALID_SOCKET;//客户端套接字
 SOCKADDR_IN ServerAddr = { 0 };//服务端地址
 USHORT uPort = 18000;//服务端端口
 //初始化套接字
 if (WSAStartup(MAKEWORD(2, 2), &wsaData))
 {
  printf("WSAStartup failed with error code: %d\n", WSAGetLastError());
  return -1;
 }
 //判断套接字版本
 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
 {
  printf("wVersion was not 2.2\n");
  return -1;
 }
 //创建套接字
 ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 if (ClientSocket == INVALID_SOCKET)
 {
  printf("socket failed with error code: %d\n", WSAGetLastError());
  return -1;
 }
 //输入服务器IP
 printf("Please input server IP:");
 char IP[32] = { 0 };
 gets_s(IP);
 //设置服务器地址
 ServerAddr.sin_family = AF_INET;
 ServerAddr.sin_port = htons(uPort);//服务器端口
 ServerAddr.sin_addr.S_un.S_addr = inet_addr(IP);//服务器地址

 printf("connecting......\n");
 //连接服务器
 if (SOCKET_ERROR == connect(ClientSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr)))
 {
  printf("connect failed with error code: %d\n", WSAGetLastError());
  closesocket(ClientSocket);
  WSACleanup();
  return -1;
 }
 printf("Connecting server successfully IP:%s Port:%d\n",
  IP, htons(ServerAddr.sin_port));
 printf("Please input your UserName: ");
 gets_s(userName);
 send(ClientSocket, userName, sizeof(userName), 0);
 printf("Please input the ChatName: ");
 gets_s(chatName);
 send(ClientSocket, chatName, sizeof(chatName), 0);
 printf("\n\n");

 _beginthreadex(NULL, 0, ThreadRecv, &ClientSocket, 0, NULL); //启动接收和发送消息线程
 _beginthreadex(NULL, 0, ThreadSend, &ClientSocket, 0, NULL);
 for (int k = 0;k < 1000;k++)
  Sleep(10000000);
 closesocket(ClientSocket);
 WSACleanup();
 return 0;
}

int main()
{
 ConnectServer(); //连接服务器
 return 0;
}

最后,需要改进的有以下几点:
1.没有消息记录,所以最好用文件或者数据库的方式记录,个人推荐数据库。

2.没有用户注册,登陆的操作,也是用文件或者数据库来弄。程序一运行就读取数据库信息就行。

3.群聊功能没有弄,这个其实很简单,就是服务器不管3721,把接收到的消息转发给所有在线用户。

4.没有离线消息,这个就用数据库存储离线消息,然后用户上线后立即发送过去就行。

最后总结一下,没有数据库的聊天程序果然功能简陋~,C语言写的程序要注意对内存的操作。还有TCP方式的连接太费时费内存(用户量达的时候)。

C语言版聊天程序(TCP版本,接下来还有UDP版本)到这里结束~,欢迎各位提出自己的看法。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C语言对栈的实现基本操作

    c语言中栈是一种数据结构,后进先出,即最后进入栈的数据最先弹出.c语言中没有栈这种数据类型,需要自己编程构建.下面我们就一起来了解一下c语言中栈的基本操作. C语言对栈的实现基本操作,操作如下: #include <stdio.h> #include <malloc.h> #include <stdlib.h> #include <stdbool.h> typedef struct Node { int data; struct Node * pNext;

  • windows中使用C# 调用 C语言生成的dll

    首先建立一个C语言源文件test.c void swap(int* a, int* b) { int c = *a; *a = *b; *b = c; } 然后下载mingw64,解压,进入到bin目录,查看是否有gcc.exe ,只要下载正确肯定是有的,可以把这个bin目录加入环境变量,就可以在任意地方运行gcc.偷懒的做法是直接把刚才做好的test.c复制到这个bin目录中,和gcc.exe在一个目录,然后在此目录下,按住shift键不松,再在空白处点击鼠标右键,就可以在右键菜单看见"在此目

  • C语言实现的猴子分桃问题算法解决方案

    本文实例讲述了C语言实现的猴子分桃问题算法.分享给大家供大家参考,具体如下: 问题: 海滩上有一堆桃子,五只猴子来分.第一只猴子把这堆桃子凭据分为五份,多了一个,这只猴子把多的一个扔入海中,拿走了一份.第二只猴子把剩下的桃子又平均 分成五份,又多了一个,它同样把多的一个扔入海中,拿走了一份,第三.第四.第五只猴子都是这样做的,问海滩上原来最少有多少个桃子? 程序: #include<stdio.h> int divided(int n, int m) //注意该递归函数的定义 { if(n/5

  • C语言 经典题目螺旋矩阵 实例详解

    C语言 经典题目螺旋矩阵 //N阶螺旋矩阵 #include <stdio.h> #include <stdlib.h> int main() { int N,i,j,n,num=1; int a[10][10]={0}; printf("输入你要输出的几阶中断:"); scanf("%d",&N); for(n=0;n<=N/2;n++) { for(j=n;j<=N-n-1;j++) a[n][j]=num++; fo

  • C语言解决螺旋矩阵算法问题的代码示例

    赶集网校招就采用了螺旋输出矩阵作为程序题,要求将矩阵螺旋输出如: 图中6*6矩阵线条所示为输出顺序,如果输出正确的话应该输出1~36有序数字.  我想的是这么做的: #include <stdio.h> //#define LEN 1 //#define LEN 2 //#define LEN 3 #define LEN 4 void printClock(int a[][LEN]){//输出函数 int t; int i = 0, m = 0; int j = LEN, n = LEN; w

  • C语言中while与do-while的介绍与注意事项

    一.while和do-while的简介  1). while语句  语法: while(表达式){ 循环体; } 循环过程: 1.先判断表达式,是否为真,如果为真跳转到2,否则跳转到3 2.执行循环体,执行完毕,跳转到1 3.跳出循环 2). do-while语句 语法: do{ 循环体; }while(表达式);  注意:这个while后面的小括号必须接; 循环过程: 1.先执行循环体,执行完毕跳转到2 2.判断表达式的结果是否为真,如果为真,跳转到1,否则跳转到3 3.跳出循环 3). do

  • C语言 冒泡排序算法详解及实例

    C语言 冒泡排序算法 冒泡排序(Bubble Sort)是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端. 冒泡排序对n个项目需要O(n2)的比较次数,且可以原地排序.尽管这个算法是最简单了解和实作的排序算法之一,但它对于少数元素之外的数列排序是很没有效率的. 冒泡排序是与插入排序拥有相等的执

  • socket多人聊天程序C语言版(一)

    首先,不要一步登天直接解决多人聊天这个问题,先把问题化简. 1.多人聊天的核心问题是服务器如何标识不同的客户端,如何根据客户端的需求转发消息给指定客户端. 2.多人聊天转化为C-C聊天,但是不再是直接C-C,而是通过server转发消息,所以变成==>C-S-C. 3.server如何允许2个client同时连接,设置listen函数的第二个参数,最大连接数. 4.server如何标识两个client,用一个结构体数组来存放两个client的信息. 5.server如何转发消息给client,很

  • C语言实现的猴子吃桃问题算法解决方案

    本文实例讲述了C语言实现的猴子吃桃问题.分享给大家供大家参考,具体如下: 问题: 猴子第一天摘下N个桃子,当时就吃了一半,还不过瘾,就又吃了一个.第二天又将剩下的桃子吃掉一半,又多吃了一个.以后每天都吃前一天剩下的一半零一个.到第10天在想吃的时候就剩一个桃子了,求第一天共摘下来多少个桃子? 解析: ① 从最后一天的x=1个,倒推出前一天的个数x,需要注意的是表达式为x=2(x+1),而不是x=2x+1,注意两者之间的区别,想清楚为什么第二种不正确. ② 将该表达式作为循环9次的循环体,并在该语

  • socket多人聊天程序C语言版(二)

    socket多人聊天程序C语言版(一)地址: http://www.jb51.net/article/94938.htm 1V1实现了,1V多也就容易了.不过相对于1V1的程序,我经过大改,采用链表来动态管理.这样效率真的提升不少,至少CPU使用率稳稳的在20以下,不会飙到100了.用C语言写这个还是挺费时间的,因为什么功能函数都要自己写,不像C++有STL库可以用,MFC写就更简单了,接下来我还会更新MFC版本的多人聊天程序.好了,废话少说,进入主题. 这个程序要解决的问题如下: 1.CPU使

  • Python使用Socket实现简单聊天程序

    b2b模式的聊天工具 服务端: # 链接 while True: print('等待连接...') sock,adr = server_socket.accept() while True: try: # 接受数据 data = sock.recv(1024) print(adr[0] + '发来消息:', data.decode()) # 发送数据 send_msg = input("请输入发送内容>>").strip() sock.send(send_msg.encod

  • 基于Java的Socket多客户端Client-Server聊天程序的实现

    任务要求 编写一个简单的Socket多客户端聊天程序: 客户端程序,从控制台输入字符串,发送到服务器端,并将服务器返回的信息显示出来 服务器端程序,从客户机接收数据并打印,同时将从标准输入获取的信息发送给客户机 满足一个服务器可以服务多个客户 低配版本链接 实现代码 工具类 import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket

  • Python基于Socket实现简易多人聊天室的示例代码

    前言 套接字(Sockets)是双向通信信道的端点. 套接字可以在一个进程内,在同一机器上的进程之间,或者在不同主机的进程之间进行通信,主机可以是任何一台有连接互联网的机器. 套接字可以通过多种不同的通道类型实现:Unix域套接字,TCP,UDP等. 套接字库提供了处理公共传输的特定类,以及一个用于处理其余部分的通用接口. socket模块: 要创建套接字,必须使用套接字模块中的socket.socket()函数,该函数具有一般语法 s = socket.socket (socket_famil

  • C#聊天程序服务端与客户端完整实例代码

    本文所述为基于C#实现的多人聊天程序服务端与客户端完整代码.本实例省略了结构定义部分,服务端主要是逻辑处理部分代码,因此使用时需要完善一些窗体按钮之类的. 先看服务端代码如下: using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Net; using

  • 使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室

    一,利用Node搭建静态服务器 这个是这个项目的底层支撑部分.用来支持静态资源文件像html, css, gif, jpg, png, javascript, json, plain text等等静态资源的访问.这里面是有一个mime类型的文件映射. mime.js /** * mime类型的 map * @ author Cheng Liufeng * @ date 2014/8/30 * 当请求静态服务器文件的类型 html, css, gif, jpg, png, javascript,

  • Java基于Socket实现多人聊天室

    本文实例为大家分享了Java基于Socket实现简易版多人聊天室的具体代码,供大家参考,具体内容如下 一. 聊天室需求 1.一个服务端,多个客户端:2.实现客户端和服务端的交互:3.客户端发送信息,服务端收到信息,再转发给其他客户端:4.上下线时显示哪个客户端上下线并且显示在线客户端数量: 二.代码分析 1. 建立连接 客户端类,创建发送端Socket对象,用自己的IP地址和端口号,与服务端建立连接. class Client: //用于与服务端通信的Socket private Socket

  • Python基于Socket实现的简单聊天程序示例

    本文实例讲述了Python基于Socket实现的简单聊天程序.分享给大家供大家参考,具体如下: 需求:SCIENCE 和MOOD两个人软件专业出身,厌倦了大众化的聊天软件,想着自己开发一款简易的聊天软件,满足他们的个性化需求,又不失"专业水准",Talk is easy, try to code it. 技术:socket,详细可参考前文:Python Socket实现简单TCP Server/client功能 语言:python 尽管socket区分服务器和客户端,但是在聊天程序中两

  • 详解基于java的Socket聊天程序——初始设计(附demo)

    写在前面: 可能是临近期末了,各种课程设计接踵而来,最近在csdn上看到2个一样问答,那就是编写一个基于socket的聊天程序,正好最近刚用socket做了一些事,出于兴趣,自己抽了几个晚上的空闲时间敲了一个,目前仅支持单聊,群聊,文件传送这些功能.首先,贴出一个丑丑的程序图(UI是用java swing写的,这个早就忘光了,无奈看着JDK的API写了一个),如下图:  服务端设计: 服务端主要有两个操作,一是阻塞接收客户端的socket并做响应处理,二是检测客户端的心跳,如果客户端一段时间内没

随机推荐