我正在尝试创建一个仅在共享内存中具有文件的小文件服务器。客户端应该向服务器发送命令,如 CREATE、DELETE 等。但是,我还没有到那个阶段。
我已经准备了一个服务器和一个客户端。服务器接受套接字,并为每个客户端连接创建一个新线程(要求)。
当我启动客户端时,我可以成功连接到服务器并发送将被接收的消息。但是,这只能工作一次。发送我的命令后,服务器将不会收到任何其他命令。
我尝试使用换行符捕获消息,但这似乎不起作用,因此任何帮助将不胜感激。
先谢谢你。
服务器源:
/*
* main.c - the server file.
*
* Created on: Apr 26, 2014
* Author: fish-guts
*/
#include "main.h"
/* our main server buffer */
char serverbuf[4096];
static int client_sock;
void launch_app(char *argv[]) {
if ((strcmp(argv[1], "start")) == 0)
startup();
else if ((strcmp(argv[1], "stop")) == 0)
stop_server();
else {
fprintf(stderr,
"Invalid Command: %s. Valid Commands are ./fileserver [start|stop]\n",
argv[1]);
exit(EXIT_FAILURE);
}
}
int main(int argc, char* argv[]) {
if (argc > 1)
launch_app(argv);
else {
fprintf(stderr,
"No argument supplied. Valid Argument are [start|stop]\n");
exit(EXIT_SUCCESS);
}
return 0;
}
void print_start_msg(void) {
fprintf(stderr, "###############################\n");
fprintf(stderr, "Welcome to Severin'ŝ FileServer\n");
fprintf(stderr, "###############################\n");
}
void stop_server(void) {
exit(EXIT_SUCCESS);
}
void startup(void) {
print_start_msg();
start_server();
}
void start_server(void) {
int s, len, rc;
int tid;
long t;
char buf[100000];
struct sockaddr_in addr;
struct sockaddr_in client;
pthread_t client_thread;
sock = socket(AF_INET, SOCK_STREAM, 0);
unsigned short port = PORT;
// clear the struct
memset((char*) &addr, 0, sizeof(addr));
fprintf(stderr, "\n\nStarting server...");
// let's set some values
/* type of socket created in socket() */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons((unsigned short) PORT);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
/* bind the socket to the port specified above */
if ((rc = bind(sock, (struct sockaddr *) &addr, sizeof(addr))) < 0) {
fprintf(stderr, "Error binding address: %s\n", strerror(errno));
exit(EXIT_FAILURE);
} else {
fprintf(stderr, "Bind Successful\n");
}
if ((listen(sock, serverbuf) < 0)) {
fprintf(stderr, "Listen Failed\n");
exit(EXIT_FAILURE);
} else {
fprintf(stderr, "Server started successfully, listening on port %d\n",
PORT);
}
// the main server loop
while (!quitting) {
len = sizeof(struct sockaddr_in);
client_sock = accept(sock, (struct sockaddr *) &client, &len);
if (client_sock < 0) {
fprintf(stderr, "Accept failed\n");
} else {
/* This is the client process */
tid = pthread_create(&client_thread, NULL, doprocessing, (void*) t);
if (tid) {
fprintf(stderr, "Error creating thread: %d\n", tid);
}
}
}
}
void *doprocessing(void) {
int n;
int s, len, rc;
char buf[100000];
char *str = "Welcome\n";
bzero(buf, 100000);
n = write(client_sock, str, sizeof(str));
if (n < 0) {
fprintf(stderr, "ERROR writing to socket");
exit(1);
}
s = recv(client_sock, buf, sizeof(serverbuf),0);
if (s) {
fprintf(stderr,"Bytes received: %i\n",s);
buf[s] = 0;
// we use CRLF as a line breaker, its easier to parse the commands
char *pch = strtok(buf, "\n");
while (pch != NULL) {
strcpy(serverbuf, pch);
fprintf(stderr, "Command: %s\n", buf);
//TODO: add command handler
//parse();
serverbuf[s] = 0;
pch = strtok(NULL, "\r\n");
//addlog(1, serverbuf);
}
} else {
fprintf(stderr,"No data received\n");
}
}
客户来源:
#include "main.h"
#define PORT 8083
#define BUF_SIZE 1024
int quitting;
void start_client(const char *address);
int main(int argc, char* argv[]) {
start_client("localhost");
}
void start_client(const char *address) {
struct hostent *he;
struct sockaddr_in server;
int s;
char buf[BUF_SIZE];
char input[BUF_SIZE];
sock = socket(AF_INET, SOCK_STREAM, 0);
if ((he = gethostbyname(address)) == NULL) {
fprintf(stderr,"error resolving hostname..");
exit(1);
}
/*
* copy the network address part of the structure to the
* sockaddr_in structure which is passed to connect()
*/
memcpy(&server.sin_addr, he->h_addr_list[0], he->h_length);
server.sin_family = AF_INET;
server.sin_port = htons((unsigned short)PORT);
/* connect */
if (connect(sock, (struct sockaddr *) &server, sizeof(server))) {
puts("Error connecting...\n");
exit(1);
} else {
fprintf(stderr,"Connected to server\n");
}
send(sock,"Hallo Server\n",BUF_SIZE,0);
int i = 0;
while(!quitting) {
if(i<100) {
send(sock,"yallo",6,0);
}
fgets(input, sizeof(input), stdin);
if(send(sock,input,strlen(input),0)<0) {
fprintf(stderr,"Error sending data: %s\n",errno);
} else {
fprintf(stderr,"Hello: %s\n",buf);
}
s = recv(sock, buf, sizeof(buf),0);
if(s) {
buf[s] = 0;
fprintf(stderr,"Message from Server: %s\n",buf);
} else {
fprintf(stderr,"Error in recv: %s\n",errno);
}
}
}
处理套接字时的一些规则:
1.低级消息字段定义
永远记住,您正在读取和写入字节流。您必须记住的另一条规则是,TCP/IP并不保证一次写入等于一次读取。但是,这些规则对您意味着什么?
上述规则的组合意味着在从套接字读取之前,您必须确切地知道需要读取多少字节。所以:
(情况 1):例如,如果您要发送/接收一个四字节整数,那么他的代码应如下所示:
int myInt = 12345;
send(sockfd, &myInt, sizeof(myInt), my_flags);
在读取端:
int myReceivedInt = 0;
int received_count = recv(client_sock, &myReceivedInt, sizeof(myReceivedInt), 0);
注意:不同的平台为数据类型定义了不同的大小。
(案例2):
如果您要发送可变长度字段(例如字符串),则代码应如下所示:
// get string length
int str_size = strlen(my_str);
// send fixed-length data to pre-pend variable-length field with the latter's size
send(sockfd, &str_size, sizeof(str_size), my_flags);
// send the variable-length field.
send(sockfd, my_str, str_size, my_flags);
在接收端:
int string_size = 0;
char *received_string = NULL;
int received_count = recv(client_sock, &string_size, sizeof(string_size), 0);
/*
now we know how big the string is, so we allocate
memory for it or use a previously allocated buffer. This is omitted...
*/
int received_count = recv(client_sock, &received_string, string_size, 0);
received_string[string_size] = '\0';
上述两条规则的另一个后果是,您可能需要从套接字读取多次才能接收一条完整的消息。对于较大的消息(例如文件传输)尤其如此。因此,当接收到大消息时,将recv()
保持循环并继续读取,直到您阅读了整个消息。
例如,如果您正在读取文件:
int file_size = 0, read_so_far = 0, ret = 0;
recv(sockfd, &file_size , sizeof(file_size), 0);
// now we know how big is the file...allocate buffer (file_content) and read file fully
while(read_so_far != file_size)
{
ret = recv(sockfd, file_content + read_so_far, file_size - read_so_far, 0);
if(ret < 0)
{
// handle error case, socket reset maybe?
perror("Something bad happened with the socket");
break;
}
read_so_far += ret;
}
2.定义协议
现在您已经了解了低级内容,您可以定义协议。该协议是对要通过连接发送的消息格式的描述。每条消息都由一个或多个字段组成,如上所示。
3. 定义消息
请记住,每条消息都应定义一个命令和命令的参数。例如,删除文件的消息应包含命令“删除”和“文件名”。因此,删除文件消息可以定义为:
对其他消息做同样的事情,您最终会得到协议。代码可能如下所示:
char command = 0;
s = recv(client_sock, &command, 1,0);
if(command == LIST_NODES_COMMAND)
{
// read arguments for command and process it.
} else if(command == CREATE_FOLDER_COMMAND)
{
// read arguments for command and process it.
}
4. 消息处理循环
服务器的最后一步是将消息处理放在循环中:
while(1)
{
char command = 0;
s = recv(client_sock, &command, 1,0);
if(command == LIST_NODES_COMMAND)
{
// handle list command here.
} else if(command == CREATE_FOLDER_COMMAND)
{
// read params like above and handle command.
} else if (command == COMMAND_QUIT)
{
// do the stuff necessary before the client disconnects.
}
}
我最近开始学习php套接字。我想在服务器和客户端之间创建一个永久传输控制协议!但是我的PHP套接字客户端只发送和接收一条消息。我想无限期地发送和接收消息,通过一个连接。 服务器php: 客户php:
我一直在开发一个简单的python套接字聊天室,客户端和服务器可以在其中相互发送消息。我遇到的问题是服务器和客户端一次只能发送一条消息。我希望它能像任何其他聊天室一样工作,在那里我可以在发送消息时收到消息,任何帮助都会有很大帮助
如果我不关闭套接字: 客户端没有输出。服务器从不发送消息,或者客户端从不接收消息。 有人知道发生这种情况的可能原因吗?客户端使用一个线程接收消息,一个线程发送消息。客户端套接字在主客户端线程中创建,因此接收者和发送者线程使用当前套接字进行通信。 提前谢了。
我在询问之前搜索了这个问题,但我找不到类似的东西。我开发了一个客户端/服务器解决方案来发送/接收HL7消息。我使用套接字将客户端连接到服务器,从这个连接中,我只能使用OutputSteam对象发送1条HL7消息。我如何在同一个套接字连接中发送多个HL7?我尝试了不同的方法,但它们不能正常工作。 以下是我的客户端代码: 从服务器端 如何在同一套接字连接中发送更多HL7消息?
现在我有了下面的类,它使用OkHttp处理WebSockets,但它的设置方式是,我无法保持WebSocket打开,以便向web Socket发送新消息。如何在不创建新的websocket连接的情况下继续向同一个打开的websocket发送消息?
我有一个关于如何改进这个代码的问题。我是Socket.io的新手,我一直在YouTube上看一个关于私人信息的视频教程。我只是想知道有没有更好的方法来改进下面的代码行? 但似乎不起作用。