局域网聊天程序模型

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

问题比较多,大家能答就答,一点也好,全部回答更好 ^_^,有劳大家。。
...全文
312 点赞 收藏 21
写回复
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
完全不用考虑线程和进程的问题。

回复 点赞
某某寕 2010年04月23日
谷歌+ 百度~!
回复 点赞
发动态
发帖子
C++ 语言
创建于2007-09-28

3.1w+

社区成员

24.8w+

社区内容

C++ 语言相关问题讨论,技术干货分享
社区公告
暂无公告