局域网聊天程序模型

Non_Recursive 2010-04-23 01:09:57
大家好,有没有写过局域网聊天程序或对这块比较了解的,我想问一下两个客户端之间的通过server通信架构是怎样的?如图:

client1---send msg--->server---forward msg--->client2 同理,client2也能向client1发送信息。。

我的想法是这样的,首先client都要先注册到server(注册结构体含:userID,name,password,ipaddress..等),然后如上图所示进行聊天,如果用UDP的话,应该可以实现,但是如果我想发文件呢?发文件一般是用TCP吧,就不知道怎么做了。。

整理一下(系统是linux内核,ubuntu 8.10,语言:C/C++ ):

Q1:两个client如何通过server通信,用UDP跟TCP有什么不同及要注意的地方,主要是怎样实现?有哪些函数介绍?

Q2:如果我想在一台电脑上开两个客户端(客户端都是通过IP注册到server的),跟另外不同的(或相同的)客户聊天,能实现吗?原理是怎样,是否有函数或资料介绍。

Q3:因为要发送文件,所以我想用多进程实现,大家觉得这样的聊天程序是多进程好,还是多线程好,多线程比较不好控制。。这方面有没有什么资料推荐。。

问题比较多,大家能答就答,一点也好,全部回答更好 ^_^,有劳大家。。
...全文
353 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
liang118038liang 2010-04-24
  • 打赏
  • 举报
回复
局域网就干脆直接用UDP广播可以啦!
linganxiong 2010-04-24
  • 打赏
  • 举报
回复
不错不错
na2650945 2010-04-24
  • 打赏
  • 举报
回复
MARK下。
以后会用到。
heis07w 2010-04-24
  • 打赏
  • 举报
回复
unix网络编程前几章,基本可以解决了。
顶5L
shiweifu 2010-04-24
  • 打赏
  • 举报
回复
如果打算实现外网给内网发,LZ还要考虑实现P2P
shiweifu 2010-04-24
  • 打赏
  • 举报
回复
人家说的是LINUX下。。
LZ到底是用C还是C++?
C就得自己封装+调用了
发送文字性的可以服务器中转 顺便也可以过滤下(有密码阿什么的关键字给劫下来,呵呵)
文件可以判断下大小,如果小于多少,就中转,如果大于这个值,就给客户端A发个消息,让A再开个线程和端口,开完了告诉服务器,已经准备好了,再把端口和IP发送给B,然后他俩就开始传了
cattycat 2010-04-24
  • 打赏
  • 举报
回复
发文件比较大,就不要server转发了,让server告诉两个客户端相互的IP,然后两个客户端创建子进程创建tcp的socket来传送文件,这样就有保证了。
zhangweiit 2010-04-24
  • 打赏
  • 举报
回复
Q1:两个client如何通过server通信,用UDP跟TCP有什么不同及要注意的地方,主要是怎样实现?有哪些函数介绍?
聊天类型的通信,不像金融这一类需要非常强的实时性与准确性,可以用UDP
我们游戏也是基于UDP类型的,因为UDP不需要保持连接占用资源更低

Q2:如果我想在一台电脑上开两个客户端(客户端都是通过IP注册到server的),跟另外不同的(或相同的)客户聊天,能实现吗?原理是怎样,是否有函数或资料介绍。
如果开两个客户端的话,那就要开两个端口了

Q3:因为要发送文件,所以我想用多进程实现,大家觉得这样的聊天程序是多进程好,还是多线程好,多线程比较不好控制。。这方面有没有什么资料推荐。。
发送文件当然是多线程了
如果你觉得多线程都不好控制了,那多进程就更难控制了
xiaolinxianju 2010-04-24
  • 打赏
  • 举报
回复
加分,帮顶
Non_Recursive 2010-04-24
  • 打赏
  • 举报
回复
先谢谢大家,其实我现在也不大想用server来转发了,对下面的问题比较兴趣

[Quote=引用 18 楼 shiweifu 的回复:]
如果打算实现外网给内网发,LZ还要考虑实现P2P
[/Quote]

请问一下这个怎么实现呢,楼上也有人提到UDP打洞,我对NAT还算了解,但编码就差了点,不知怎么实现。。

还有啊,外网跟内网通信,第一次通信时,怎么知道对方的IP呢?
通信双方都注册到server,这样server是知道客户端的IP了,但客户之间怎么知道相互的IP呢(根据客户ID让SERVER告诉客户端)?

ForestDB 2010-04-23
  • 打赏
  • 举报
回复
帮顶。
Non_Recursive 2010-04-23
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 caomuyong1 的回复:]

晕,同一个局域网还通过SERVER。首先连接到SERVER,让SERVER告诉所有成员的IP,然后直接用内网IP发就可以了。
外网也没必要通过SERVER转发消息,NAT打洞直接UDP发就得了。
[/Quote]
主要是为了练手,所以想学一下怎样通过server来转发,楼上很多朋友给了C/S的简单架构跟源码,这些说实在,我已经很熟悉了,但就是不知道怎样用server来转发,主要考虑到代码可读性等。

不通过server转发也行,其实主要还是传文件那块,聊天用UDP,传输文件用TCP。。晕了,还是不通过server来转发好了,这位大哥提到NAT打洞,原理我懂一点,但没实现过,不知可否告之一二(给份代码,非常感谢。。
)
yanran_hill 2010-04-23
  • 打赏
  • 举报
回复
哎,不是有开源的ICQ和IpMsg吗?一个使用TCP通信聊天,一个使用UDP组播发消息,看一下代码应该就能明白了
AlanBruce 2010-04-23
  • 打赏
  • 举报
回复
通信先看看客户服务端吧

C/S最起码要熟悉吧

再谈代码吧
caomuyong1 2010-04-23
  • 打赏
  • 举报
回复
晕,同一个局域网还通过SERVER。首先连接到SERVER,让SERVER告诉所有成员的IP,然后直接用内网IP发就可以了。
外网也没必要通过SERVER转发消息,NAT打洞直接UDP发就得了。
hyf62399 2010-04-23
  • 打赏
  • 举报
回复
以下基本socket通信代码可供你参考下:
用TCP实现client.cpp
#include <Winsock2.h>
#include <stdio.h>

void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 1, 1 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}


if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup( );
return;
}
SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);

SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);
connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

char recvBuf[100];
recv(sockClient,recvBuf,100,0);
printf("%s\n",recvBuf);
send(sockClient,"This is lisi",strlen("This is lisi")+1,0);

closesocket(sockClient);
WSACleanup();
}
sevice.cpp端实现:
#include <Winsock2.h>
#include <stdio.h>

void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 1, 1 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}


if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup( );
return;
}
SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);

SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);

bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

listen(sockSrv,5);

SOCKADDR_IN addrClient;
int len=sizeof(SOCKADDR);

while(1)
{
SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);
char sendBuf[100];
sprintf(sendBuf,"Welcome %s to http://www.sunxin.org",
inet_ntoa(addrClient.sin_addr));
send(sockConn,sendBuf,strlen(sendBuf)+1,0);
char recvBuf[100];
recv(sockConn,recvBuf,100,0);
printf("%s\n",recvBuf);
closesocket(sockConn);
}
}

UDP就不帖了~自己多看看socket吧!
hahalxp 2010-04-23
  • 打赏
  • 举报
回复
xiuxianshen 2010-04-23
  • 打赏
  • 举报
回复
可以去看看孙鑫的教材
http://v.youku.com/v_show/id_XMjYzNDAxNjg=.html
linsen_519 2010-04-23
  • 打赏
  • 举报
回复
A1 udp没有重发机制,有可能会丢包,常用于非重要场合,如QQ
Tcp有重发机制,不可能丢包,常用于重要场合,如银行交易系统
如果你想用udp点对点传输文件,有可能不能通过防火墙(局域网不怕),所以建议使用tcp功过server传输
A2 当然可以~

A3你说到线程,我就要问你是用什么库写了~
我这两天刚刚写了一个简单的聊天工具,用的是boos/asio.hpp里面的异步IO
完全不用考虑线程和进程的问题。

某某9 2010-04-23
  • 打赏
  • 举报
回复
谷歌+ 百度~!
加载更多回复(1)

64,671

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧