//服务端server.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define SERVPORT 6000 /*服务器监听端口号 */
#define BACKLOG 10 /* 最大同时连接请求数 */
#define MAXDATASIZE 100
main()
{
char buf[MAXDATASIZE];
int sockfd,client_fd; /*sock_fd:监听socket;client_fd:数据传输socket */
struct sockaddr_in my_addr; /* 本机地址信息 */
struct sockaddr_in remote_addr; /* 客户端地址信息 */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket创建出错!");
exit(1);
}
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(SERVPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero),8);
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
perror("bind出错!");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1)
{
perror("listen出错!");
exit(1);
}
while(1)
{
sin_size = sizeof(struct sockaddr_in);
if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size)) == -1)
{
perror("accept出错");
continue;
}
printf("received a connection from %s\n", inet_ntoa(remote_addr.sin_addr));
if (!fork())
{ /* 子进程代码段 */
if ((recvbytes=recv(client_fd, buf, MAXDATASIZE, 0)) ==-1)
{
perror("recv出错!");
close(client_fd);
exit(0);
}
buf[recvbytes] = '\0';
printf("from client Received: %s",buf);
if (send(client_fd, "thanks!\n", 8, 0) == -1)
perror("send出错!");
close(client_fd);
exit(0);
}
close(client_fd);
}
}
//客户端client.c
#include<stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define SERVPORT 6000
#define MAXDATASIZE 100
main(int argc, char *argv[])
{
int sockfd, recvbytes;
char buf[MAXDATASIZE];
struct hostent *host;
struct sockaddr_in serv_addr;
if (argc < 2)
{
fprintf(stderr,"Please enter the server's hostname!\n");
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL)
{
herror("gethostbyname出错!");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket创建出错!");
exit(1);
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVPORT);
serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(serv_addr.sin_zero),8);
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect出错!");
exit(1);
}
if (send(sockfd, "hello!\n", 7, 0) == -1)
{
perror("send出错!");
exit(1);
}
if ((recvbytes=recv(sockfd, buf, MAXDATASIZE, 0)) ==-1)
{
perror("recv出错!");
exit(1);
}
buf[recvbytes] = '\0';
printf("Received: %s",buf);
close(sockfd);
}
⑵ Linux中本机和本机Socket通信会走网卡吗
我写一个测试程序,结论是:不需要走网卡。
我生成了一个5G的大文件。同时传输的过程中,我把网卡拔掉,最后数据传输完毕。
不过这是一个很傻逼的行为,因为直接把网卡拔掉就可以测试。
至于原因 @pansz已经提到了。 虽然我行为是傻逼了点,不过写这个程序的过程中还是收获不少呢,因为刚学网络编程,多挖几个坑还自己还是有好处的。
代码如下:
生成文件的代码:
#define SIZE 5000000
#define OPEN_MODE 00777
int main(int argc,char **argv){
srand(time(NULL));
int fd=open("output.txt",O_APPEND|O_RDWR);
int n=0;
char buf[1024]={0};
for(int i=0;i<SIZE;i++){
for(int j=0;j<1023;j++){
buf[j]=(char)(rand()%94+32);
}
buf[1023]='\0';
n=write(fd,buf,1024);
}
close(fd);
return 0;
}
Client
int len=0;
while((len=read(fd,sendline,1024))){
if( send(sockfd,sendline,strlen(sendline), 0) < 0)
{
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
if((rec_len = recv(sockfd, buf, MAXLINE,0)) == -1) {
perror("recv error");
exit(1);
}
memset(sendline,0,1024);
buf[rec_len] = '\0';
printf("Received : %s ",buf);
}
close(sockfd);
Server
void Server::EventLoop(){
int fd=open("re.txt",O_APPEND | O_RDWR);
cout<<"waiting for client's request."<<endl;
if((cfd=accept(sfd,reinterpret_cast<struct sockaddr*>(NULL),NULL))==-1){
std::cerr<<"acceprt error!"<<endl;
}
while(1){
nread=recv(cfd,buf,BUF_SIZE,0);
buf[nread]='\0';
write(fd,buf,nread);
printf("the size is: %zd\n",nread);
if(send(cfd,"Yeah I have receive your message.\n",40,0)==-1){
std::cerr<<"send error."<<endl;
exit(-1);
}
}
close(sfd);
}
⑶ linux系统的进程间通信有哪几种方式
一、方式
1、管道(Pipe)及有名管道( mkpipe):
管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
2、信号(Signal):
信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身。
linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction。
实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数。
3、消息队列(Message):
消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
4、共享内存:
使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
5、信号量(semaphore):
主要作为进程间以及同一进程不同线程之间的同步手段。
6、套接口(Socket):
更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
二、概念
进程间通信概念:
IPC—-InterProcess Communication
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到所以进程之间要交换数据必须通过内核。
在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。
(3)linuxsocket本地通信扩展阅读
1)无名管道:
管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)。
管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,构成两进程间通信的一个媒介。
数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
2)有名管道:
不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间)。
因此,通过FIFO不相关的进程也能交换数据。值得注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。
⑷ Linux下Socket编程 怎样实现客户端之间互相通信
网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。
下面用Socket实现一个windows下的c语言socket通信例子,这里我们客户端传递一个字符串,服务器端进行接收。
【服务器端】
#include"stdafx.h"
#include<stdio.h>
#include<winsock2.h>
#include<winsock2.h>
#defineSERVER_PORT5208//侦听端口
voidmain()
{
WORDwVersionRequested;
WSADATAwsaData;
intret,nLeft,length;
SOCKETsListen,sServer;//侦听套接字,连接套接字
structsockaddr_insaServer,saClient;//地址信息
char*ptr;//用于遍历信息的指针
//WinSock初始化
wVersionRequested=MAKEWORD(2,2);//希望使用的WinSockDLL的版本
ret=WSAStartup(wVersionRequested,&wsaData);
if(ret!=0)
{
printf("WSAStartup()failed! ");
return;
}
//创建Socket,使用TCP协议
sListen=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sListen==INVALID_SOCKET)
{
WSACleanup();
printf("socket()faild! ");
return;
}
//构建本地地址信息
saServer.sin_family=AF_INET;//地址家族
saServer.sin_port=htons(SERVER_PORT);//注意转化为网络字节序
saServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//使用INADDR_ANY指示任意地址
//绑定
ret=bind(sListen,(structsockaddr*)&saServer,sizeof(saServer));
if(ret==SOCKET_ERROR)
{
printf("bind()faild!code:%d ",WSAGetLastError());
closesocket(sListen);//关闭套接字
WSACleanup();
return;
}
//侦听连接请求
ret=listen(sListen,5);
if(ret==SOCKET_ERROR)
{
printf("listen()faild!code:%d ",WSAGetLastError());
closesocket(sListen);//关闭套接字
return;
}
printf("Waitingforclientconnecting! ");
printf("Tips:Ctrl+ctoquit! ");
//阻塞等待接受客户端连接
while(1)//循环监听客户端,永远不停止,所以,在本项目中,我们没有心跳包。
{
length=sizeof(saClient);
sServer=accept(sListen,(structsockaddr*)&saClient,&length);
if(sServer==INVALID_SOCKET)
{
printf("accept()faild!code:%d ",WSAGetLastError());
closesocket(sListen);//关闭套接字
WSACleanup();
return;
}
charreceiveMessage[5000];
nLeft=sizeof(receiveMessage);
ptr=(char*)&receiveMessage;
while(nLeft>0)
{
//接收数据
ret=recv(sServer,ptr,5000,0);
if(ret==SOCKET_ERROR)
{
printf("recv()failed! ");
return;
}
if(ret==0)//客户端已经关闭连接
{
printf("Clienthasclosedtheconnection ");
break;
}
nLeft-=ret;
ptr+=ret;
}
printf("receivemessage:%s ",receiveMessage);//打印我们接收到的消息。
}
//closesocket(sListen);
//closesocket(sServer);
//WSACleanup();
}
【客户端】
#include"stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<winsock2.h>
#defineSERVER_PORT5208//侦听端口
voidmain()
{
WORDwVersionRequested;
WSADATAwsaData;
intret;
SOCKETsClient;//连接套接字
structsockaddr_insaServer;//地址信息
char*ptr;
BOOLfSuccess=TRUE;
//WinSock初始化
wVersionRequested=MAKEWORD(2,2);//希望使用的WinSockDLL的版本
ret=WSAStartup(wVersionRequested,&wsaData);
if(ret!=0)
{
printf("WSAStartup()failed! ");
return;
}
//确认WinSockDLL支持版本2.2
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup();
printf("InvalidWinSockversion! ");
return;
}
//创建Socket,使用TCP协议
sClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sClient==INVALID_SOCKET)
{
WSACleanup();
printf("socket()failed! ");
return;
}
//构建服务器地址信息
saServer.sin_family=AF_INET;//地址家族
saServer.sin_port=htons(SERVER_PORT);//注意转化为网络节序
saServer.sin_addr.S_un.S_addr=inet_addr("192.168.1.127");
//连接服务器
ret=connect(sClient,(structsockaddr*)&saServer,sizeof(saServer));
if(ret==SOCKET_ERROR)
{
printf("connect()failed! ");
closesocket(sClient);//关闭套接字
WSACleanup();
return;
}
charsendMessage[]="hellothisisclientmessage!";
ret=send(sClient,(char*)&sendMessage,sizeof(sendMessage),0);
if(ret==SOCKET_ERROR)
{
printf("send()failed! ");
}
else
printf("clientinfohasbeensent!");
closesocket(sClient);//关闭套接字
WSACleanup();
}
⑸ Linux编程socket通信疑问
什么是Socket
Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。要学Internet上的TCP/IP网络编程,必须理解Socket接口。
Socket接口设计者......
答案就在这里:linux
socket
通信编程
----------------------Hi,地球人,我是问答机器人小S,上面的内容就是我狂拽酷炫叼炸天的答案,除了赞同,你还有别的选择吗?
⑹ Linux C 网络编程....使用socket通讯...
你可能使用的是TCP连接,这是基于连接发送,是流式传输,没有边界。
不过一般都有一个缓冲回区,满答了后才发送出去,要想没满就发送的话,就得使用推。
一个很重要的原因可能是你send的时候传入的第3个实参有问题。
另外有一点可能是低潮限制造成的。
可以用SO_SNDLOWAT套接字选项设置一个大一点的低潮。
另外你这样发送,可能会有主机大小端影响。最好是作为文本串来传输。
⑺ Linux 进程间套接字通信(Socket)基础知识
姓名:罗学元 学号:21181214375 学院:广州研究院
【嵌牛导读】Linux进程间套接字通信基础
【嵌牛鼻子】Linux 进程间套接字及通信介绍
【嵌牛提问】Linux进程间套接字包含哪些内容,如何实现通信
一、套接字(Socket)通信原理
套接字通信允许互联的位于不同计算机上的进程之间实现通信功能。
二、套接字的属性
套接字的特性由3个属性确定,它们分别是:域、类型和协议。
1. 套接字的域
它指定套接字通信中使用的网络介质,最常见的套接字域是AF_INET,它指的是Internet网络。当客户使用套接字进行跨网络的连接时,它就需要用到服务器计算机的IP地址和端口来指定一台联网机器上的某个特定服务,所以在使用socket作为通信的终点,服务器应用程序必须在开始通信之前绑定一个端口,服务器在指定的端口等待客户的连接。
另一个域AF_UNIX表示UNIX文件系统,就是文件输入/输出,它的地址就是文件名。
2. 套接字类型
因特网提供了两种通信机制:流(stream)和数据报(datagram),因而套接字的类型也就分为流套接字和数据报套接字。我们主要看流套接字。
流套接字由类型SOCK_STREAM指定,它们是在AF_INET域中通过TCP/IP连接实现,同时也是AF_UNIX中常用的套接字类型。
流套接字提供的是一个有序、可靠、双向字节流的连接,因此发送的数据可以确保不会丢失、重复或乱序到达,而且它还有一定的出错后重新发送的机制。
与流套接字相对的是由类型SOCK_DGRAM指定的数据报套接字,它不需要建立连接和维持一个连接,它们在AF_INET中通常是通过UDP/IP实现的。它对可以发送的数据的长度有限制,数据报作为一个单独的网络消息被传输,它可能丢失、复制或错乱到达,UDP不是一个可靠的协议,但是它的速度比较高,因为它并不需要总是要建立和维持一个连接。
3.套接字协议
只要底层的传输机制允许不止一个协议来提供要求的套接字类型,我们就可以为套接字选择一个特定的协议。通常只需要使用默认值。
三、套接字地址
每个套接字都有其自己的地址格式,对于AF_UNIX域套接字来说,它的地址由结构sockaddr_un来描述,该结构定义在头文件
struct sockaddr_un{
sa_family_t sun_family; //AF_UNIX,它是一个短整型
char sum_path[]; //路径名
};
对于AF_INET域套接字来说,它的地址结构由sockaddr_in来描述,它至少包括以下几个成员:
struct sockaddr_in{
short int sin_family; //AN_INET
unsigned short int sin_port; //端口号
struct in_addr sin_addr; //IP地址
}
而in_addr被定义为:
struct in_addr{
unsigned long int s_addr;
}
四、基于流套接字的客户/服务器的工作流程
使用socket进行进程通信的进程采用的客户/服务器系统是如何工作的呢?
1.服务器端
首先,服务器应用程序用系统调用socket来创建一个套接字,它是系统分配给该服务器进程的类似文件描述符的资源,它不能与其他的进程共享。
接下来,服务器进程会给套接字起个名字,我们使用系统调用bind来给套接字命名。然后服务器进程就开始等待客户连接到这个套接字。
然后,系统调用listen来创建一个队列,并将其用于存放来自客户的进入连接。
最后,服务器通过系统调用accept来接受客户的连接。它会创建一个与原有的命名套接不同的新套接字,这个套接字只用于与这个特定客户端进行通信,而命名套接字(即原先的套接字)则被保留下来继续处理来自其他客户的连接。
2.客户端
基于socket的客户端比服务器端简单。同样,客户应用程序首先调用socket来创建一个未命名的套接字,然后讲服务器的命名套接字作为一个地址来调用connect与服务器建立连接。
一旦连接建立,我们就可以像使用底层的文件描述符那样用套接字来实现双向数据的通信。
⑻ linux下实现简单的socket通信,运行client端时需要传入哪些参数
你程序里写得很清楚啊,需要传入服务器IP地址
不带参数时 argc 为1
argv[0] 里放的是程序的路径
加了参数以后 argc = 输入参数的个数加1
argv[1] 开始才是用户输入的参数