linux下的socket编程(50分)

  • 主题发起人 oldhorsejs
  • 开始时间
O

oldhorsejs

Unregistered / Unconfirmed
GUEST, unregistred user!
在WINDOWS下可以通过API开发SOCKET程序,但在LINUX下,在不使用控件的情况下,如何用KYLIX开发SOCKET程序?
 
难道真的没有一个人知道吗?
 
另外,我按INDY主页上的步骤升级到INDY10,但是VCL面板上不能生成相应的组件,但可以通过程序单元访问,请问各位高手是怎么回事?
 
谁有LINUX下KYLIX开发经验的可以联系我,我们是深圳的一家大型高科技公司,目前在招这方面的人!
 
直接创建socket连接啊,TCP/UDP都可以实现的.
function TcpConnect():integer;
var
mysocket,Re:integer;
remotesocket: TSocketAddrIn;
MySocketBuf:array[0..256]of byte;
SendStrBuf:array[0..1024*16] of char;
PcharSocketAddr:pChar;
begin
mysocket:=socket(AF_INET,SOCK_STREAM,0);
if INVAID_SOCKET <> mysocket then
begin
Writeln('创建Socket成功');
remotesocket.sin_family:=AF_INET;

GetMem(PcharSocketAddr,Length('192.168.1.100')+1);
ZeroMemory(PcharSocketAddr,Length('192.168.1.100')+1);
StrPCopy(PcharSocketAddr,Edit1.Text);
remotesocket.sin_addr.S_addr :=inet_addr(PcharSocketAddr);
FreeMem(PcharSocketAddr);
remotesocket.sin_port := htons(StrToInt('1080'));
Re:=connect(mysocket,remotesocket,sizeof(remotesocket));
if Re <> SOCKET_ERROR then
Writeln('TCP服务器连接成功');
......
end;
end;
 
如果客户端是用其它语言开发的,用的是WINSOCK API,服务器端是LINUX下的用DELPHI开发的,用什么方式通讯好一点,直接用API呢,还是用INDY控件,如果用控件,会不会产生不兼容的情况,请各位朋友多多指教!
 
以上问题,请wangzhiye兄弟解答,多谢!
 
如果客户端是用其它语言开发的,用的是WINSOCK API,服务器端是LINUX下的用DELPHI开发的,用什么方式通讯好一点,直接用API呢,还是用INDY控件,如果用控件,会不会产生不兼容的情况,请各位朋友多多指教!
////我想不会有不兼容一说吧??都是往端口发送数据。
 
数据是兼容的,格式恐怕不兼容,要不然INDY的不同版本之间怎么会存在兼容性问题呢,举个形象的例子就是:TCPCLIENT可以和IDTCPSERVER正常通讯吗,请指点一二,呵呵
 
我的建议,用C来做开发网络,kylix可以做外层,进程间通讯用IPC搞定,socket通讯在linux下用C来不是很难的事情,贴一个去年我写的linux下组播接收数据的代码片断,这些函数在windows下都有对应。
// copyright by simahuapeng
// 05-07-01
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <time.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
/*
* 功能 :
* 初始化传输进程的资源
* 此程序只用于服务端和客户端的传输进程
*
* 输入 :
* 无
*
* 返回 :
* 成功 : 0
* 失败 : -1
*/
static inline int open_multi ()
{
int rc = -1;
int i = 1;
/* 客户程序填充服务端的资料 */
memset(&transfers_addr,0,sizeof(transfers_addr));
transfers_addr.sin_family = AF_INET;
transfers_addr.sin_addr.s_addr = inet_addr(MULTI_ADDR);
transfers_addr.sin_port = SERVE_PORT;
/* 客户程序开始建立 transfers_sock描述符 */
if((transfers_sock = socket(AF_INET,SOCK_DGRAM,0))==-1)
{
fprintf(stderr,&quot;socket Error:%s/a/n&quot;,strerror(errno));
gotodo
ne_err;
}
/* 设置端口复用 */
if (setsockopt(transfers_sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
{
fprintf(stderr,&quot;setsockopt SO_REUSEADDR error = %d./n&quot;, errno);
gotodo
ne_err;
}
/* bind到本地端口*/
if (bind(transfers_sock,(struct sockaddr *)&transfers_addr,sizeof(transfers_addr))==-1)
{
fprintf(stderr,&quot;connect Error:%s/a/n&quot;,strerror(errno));
gotodo
ne_err;
}
#ifdef SET_TTL
i = TTL_VALUE;
if (setsockopt(transfers_sock, IPPROTO_IP, IP_MULTICAST_TTL, &i, sizeof(i)) < 0)
{
fprintf(stderr,&quot;setsockopt IP_MULTICAST_TTL error = %d./n&quot;, errno);
gotodo
ne_err;
}
#endif
#ifdef SET_LOOP
/* 在同一个主机上进行广播设置套接口,作用是方便单个开发系统上测试多播IP广播 */
i = 1;
if (setsockopt(transfers_sock, IPPROTO_IP, IP_MULTICAST_LOOP, &i, sizeof(i)) < 0)
{
fprintf(stderr,&quot;tsockopt IP_MULTICAST_LOOP error = %d./n&quot;, errno);
gotodo
ne_err;
}
#endif
/* 加入多播组 */
transfers_mreq.imr_multiaddr.s_addr = transfers_addr.sin_addr.s_addr;
transfers_mreq.imr_interface.s_addr = htonl(INADDR_ANY);
/* 防止DHCP没有初始化好 */
if (setsockopt(transfers_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &transfers_mreq, sizeof(transfers_mreq)) < 0)
{
/* 添加组播路由表 */
}

/* 再来一次 */
if (setsockopt(transfers_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &transfers_mreq, sizeof(transfers_mreq)) < 0)
{
if (errno)
{
fprintf(stderr,&quot;setsockopt IP_ADD_MEMBERSHIP error = %d./n&quot;, errno);
gotodo
ne_err;
}
}
/* 创建回应包SOCKET */
if ((ack_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
fprintf(stderr,&quot;open_multi : socket UDP error = %d, j = 0./n&quot;, errno);
gotodo
ne_err;
}
if (setsockopt(ack_sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
{
fprintf(stderr,&quot;open_multi : setsockopt SO_REUSEADDR error = %d./n&quot;, errno);
gotodo
ne_err;
}
rc = 0;
done_err:
/* 判断是否失败 */
if (rc==-1)
{
/* 结束通讯 */
if ( (transfers_sock>0) && (close(transfers_sock)<0) )
{
fprintf(stderr,&quot;close transfers socket error = %d/n&quot;, errno);
}
if ( (ack_sock>0) && (close(ack_sock)<0) )
{
fprintf(stderr,&quot;close ack socket error = %d/n&quot;, errno);
}
}
return rc;
}
/*
* 功能 :
* 通过udp回复服务器数据包
* 此程序只用于客户端的传输进程
*
* 输入 :
* buff : 存放接收数据的指针
* size : 存放接收数据的内存长度
*
* 返回 :
* 成功 : 0
* 失败 : -1
*/
static inline int udp_ack (char *buff, unsigned int size)
{
int rc=-1;
unsigned int namelen = sizeof (ack_addr);
/* 回复服务器已经收到完整的数据 */
while (size > 0)
{
int len;
if ((len = sendto(ack_sock,
buff,
size,
0,
(struct sockaddr *)&ack_addr,
namelen)) < 0)
{
/* EAGAIN : 写操作被阻塞,如果设置了 O_NONBLOCK 标志,则立刻返回,并报告此错误 */
if (errno != EAGAIN)
{
fprintf(stderr,&quot;udp_ack : sendto error = %d./n&quot;, errno);
gotodo
ne_err;
}
else

{
continue;
}
}
else
if ((len != size) && (errno != EINTR))
{
fprintf(stderr,&quot;udp_ack : udp_ack size is short. error = %d./n&quot;, errno);
gotodo
ne_err;
}
buff += len;
size -= len;
}
/* 数据包发送完毕 */
rc = 0;

done_err:
return rc;
}
 
我在window下写过无数,参见对应函数。
function accept;
external winsocket name 'accept';
function bind;
external winsocket name 'bind';
function closesocket;
external winsocket name 'closesocket';
function connect;
external winsocket name 'connect';
function getpeername;
external winsocket name 'getpeername';
function getsockname;
external winsocket name 'getsockname';
function getsockopt;
external winsocket name 'getsockopt';
function htonl;
external winsocket name 'htonl';
function htons;
external winsocket name 'htons';
function inet_addr;
external winsocket name 'inet_addr';
function inet_ntoa;
external winsocket name 'inet_ntoa';
function ioctlsocket;
external winsocket name 'ioctlsocket';
function listen;
external winsocket name 'listen';
function ntohl;
external winsocket name 'ntohl';
function ntohs;
external winsocket name 'ntohs';
function recv;
external winsocket name 'recv';
function recvfrom;
external winsocket name 'recvfrom';
function select;
external winsocket name 'select';
function send;
external winsocket name 'send';
function sendto;
external winsocket name 'sendto';
function setsockopt;
external winsocket name 'setsockopt';
function shutdown;
external winsocket name 'shutdown';
function socket;
external winsocket name 'socket';
function gethostbyaddr;
external winsocket name 'gethostbyaddr';
function gethostbyname;
external winsocket name 'gethostbyname';
function getprotobyname;
external winsocket name 'getprotobyname';
function getprotobynumber;
external winsocket name 'getprotobynumber';
function getservbyname;
external winsocket name 'getservbyname';
function getservbyport;
external winsocket name 'getservbyport';
function gethostname;
external winsocket name 'gethostname';
 
to 爱元元的哥哥
我的建议,用C来做开发网络,kylix可以做外层,进程间通讯用IPC搞定,socket通讯在linux下用C来不是很难的事情,贴一个去年我写的linux下组播接收数据的代码片断,这些函数在windows下都有对应。
那就要建立两个程序,一个是用C写的网络通讯的程序,另外一个是用kylix写的外层的数据业务处理方面的程序,两个程序用IPC交换数据,但kylix也可以通过LIBC库直接调用API写socket通讯,而后者只需要建立一个进程,前者还要更麻烦一点,要维护两个进程,其中一个出现问题,整个系统就不能正常运作,我这样理解对吗?请予解答!
 
另外一个比较奇怪的现象就是,我客户端用WINSOCKET API 服务器端用IDTCPSERVER,两者都在WINDOWS下调试时都正常,如果服务器端移到了LINUX下,在调用AThread.Connection.ReadBuffer时线程为停止,请问有谁知道这是怎么回事?
 
我主要是针对这个项目的分工而言的,当然是在一个进程中会更加方便管理,不过在Linux下,使用管道pipe通讯也十分的方便,我用fork比较习惯,因此对多进程通讯的方案比较推崇,我的程序大多数采用类linux内核这样的构架,负责界面和负责通讯的程序分开写,然后利用接口来连接,这样分层的结构非常清晰,而且便于项目的分工和管理。一点小建议,莫见笑。
 
通过libc走比较清晰,不要用c的
 
结束了,感谢各位参与!
 
顶部